From 1dadb0f3e894c3ab7c38bf263e6974e81381d971 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 16:44:30 +0000 Subject: [PATCH 1/2] feat(api): adds support for unpauseing external bank accounts - adds support for CONDITIONAL_ACTION Auth Rule --- .stats.yml | 6 +- .../api/models/AccountActivityListParams.kt | 77 +- .../api/models/AuthRuleV2ApplyParams.kt | 94 +- .../models/AuthRuleV2BacktestCreateParams.kt | 2 +- .../api/models/AuthRuleV2CreateParams.kt | 5502 ++++++++++++++++- .../api/models/AuthRuleV2DraftParams.kt | 1467 ++++- .../lithic/api/models/AuthRuleV2ListParams.kt | 30 +- .../api/models/AuthRuleV2UpdateParams.kt | 466 +- .../models/AuthenticationRetrieveResponse.kt | 179 +- .../kotlin/com/lithic/api/models/Event.kt | 18 + .../com/lithic/api/models/EventListParams.kt | 12 + .../lithic/api/models/EventSubscription.kt | 12 + .../models/EventSubscriptionCreateParams.kt | 12 + ...tSubscriptionSendSimulatedExampleParams.kt | 12 + .../models/EventSubscriptionUpdateParams.kt | 12 + .../com/lithic/api/models/Transaction.kt | 24 + .../com/lithic/api/models/V2ApplyResponse.kt | 3069 ++++++++- .../com/lithic/api/models/V2CreateResponse.kt | 3070 ++++++++- .../com/lithic/api/models/V2DraftResponse.kt | 3069 ++++++++- .../com/lithic/api/models/V2ListResponse.kt | 3069 ++++++++- .../lithic/api/models/V2PromoteResponse.kt | 3070 ++++++++- .../lithic/api/models/V2RetrieveResponse.kt | 3070 ++++++++- .../com/lithic/api/models/V2UpdateResponse.kt | 3070 ++++++++- .../authRules/v2/BacktestServiceAsync.kt | 14 +- .../blocking/authRules/v2/BacktestService.kt | 14 +- .../models/AccountActivityListParamsTest.kt | 12 +- .../api/models/AuthRuleV2ApplyParamsTest.kt | 27 +- .../api/models/AuthRuleV2CreateParamsTest.kt | 19 +- .../models/AuthRuleV2ListPageResponseTest.kt | 3 + .../api/models/AuthRuleV2ListParamsTest.kt | 3 + .../api/models/AuthRuleV2UpdateParamsTest.kt | 25 +- .../AuthenticationRetrieveResponseTest.kt | 24 +- .../lithic/api/models/V2ApplyResponseTest.kt | 4 + .../lithic/api/models/V2CreateResponseTest.kt | 4 + .../lithic/api/models/V2DraftResponseTest.kt | 4 + .../lithic/api/models/V2ListResponseTest.kt | 4 + .../api/models/V2PromoteResponseTest.kt | 4 + .../api/models/V2RetrieveResponseTest.kt | 4 + .../lithic/api/models/V2UpdateResponseTest.kt | 4 + .../async/authRules/V2ServiceAsyncTest.kt | 12 +- .../blocking/authRules/V2ServiceTest.kt | 12 +- 41 files changed, 29004 insertions(+), 601 deletions(-) diff --git a/.stats.yml b/.stats.yml index bfde9d73c..829e46b33 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 169 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-117e0ee9b030a2efc3b09e189e445fb1a26fd32f1c563f385b9d7071a959c550.yml -openapi_spec_hash: e529a3fa8c3a79d3664db391683334c3 -config_hash: 22e4b128e110e2767daa9d95428ebf9d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/lithic%2Flithic-1d44bb7fad99487af1161eb24dfd5369440eda7e80ed237cbc1acc6802a7d212.yml +openapi_spec_hash: 1b6b6215b60094b76b91c56b925a251a +config_hash: ac676e77c8ca051c7aad978c26e96345 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 5bdb4b636..821c4fe1d 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 @@ -8,7 +8,6 @@ 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.core.toImmutable import com.lithic.api.errors.LithicInvalidDataException import java.time.OffsetDateTime import java.time.format.DateTimeFormatter @@ -27,9 +26,9 @@ private constructor( private val endingBefore: String?, private val financialAccountToken: String?, private val pageSize: Long?, - private val result: List?, + private val result: Result?, private val startingAfter: String?, - private val status: List?, + private val status: Status?, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { @@ -68,7 +67,7 @@ private constructor( fun pageSize(): Optional = Optional.ofNullable(pageSize) /** Filter by transaction result */ - fun result(): Optional> = Optional.ofNullable(result) + fun result(): Optional = Optional.ofNullable(result) /** * A cursor representing an item's token after which a page of results should begin. Used to @@ -77,7 +76,7 @@ private constructor( fun startingAfter(): Optional = Optional.ofNullable(startingAfter) /** Filter by transaction status */ - fun status(): Optional> = Optional.ofNullable(status) + fun status(): Optional = Optional.ofNullable(status) /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -108,9 +107,9 @@ private constructor( private var endingBefore: String? = null private var financialAccountToken: String? = null private var pageSize: Long? = null - private var result: MutableList? = null + private var result: Result? = null private var startingAfter: String? = null - private var status: MutableList? = null + private var status: Status? = null private var additionalHeaders: Headers.Builder = Headers.builder() private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() @@ -124,9 +123,9 @@ private constructor( endingBefore = accountActivityListParams.endingBefore financialAccountToken = accountActivityListParams.financialAccountToken pageSize = accountActivityListParams.pageSize - result = accountActivityListParams.result?.toMutableList() + result = accountActivityListParams.result startingAfter = accountActivityListParams.startingAfter - status = accountActivityListParams.status?.toMutableList() + status = accountActivityListParams.status additionalHeaders = accountActivityListParams.additionalHeaders.toBuilder() additionalQueryParams = accountActivityListParams.additionalQueryParams.toBuilder() } @@ -208,19 +207,10 @@ private constructor( fun pageSize(pageSize: Optional) = pageSize(pageSize.getOrNull()) /** Filter by transaction result */ - fun result(result: List?) = apply { this.result = result?.toMutableList() } + fun result(result: Result?) = apply { this.result = result } /** Alias for calling [Builder.result] with `result.orElse(null)`. */ - fun result(result: Optional>) = result(result.getOrNull()) - - /** - * Adds a single [Result] to [Builder.result]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addResult(result: Result) = apply { - this.result = (this.result ?: mutableListOf()).apply { add(result) } - } + fun result(result: Optional) = result(result.getOrNull()) /** * A cursor representing an item's token after which a page of results should begin. Used to @@ -233,19 +223,10 @@ private constructor( startingAfter(startingAfter.getOrNull()) /** Filter by transaction status */ - fun status(status: List?) = apply { this.status = status?.toMutableList() } + fun status(status: Status?) = apply { this.status = status } /** Alias for calling [Builder.status] with `status.orElse(null)`. */ - fun status(status: Optional>) = status(status.getOrNull()) - - /** - * Adds a single [Status] to [Builder.status]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addStatus(status: Status) = apply { - this.status = (this.status ?: mutableListOf()).apply { add(status) } - } + fun status(status: Optional) = status(status.getOrNull()) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -360,9 +341,9 @@ private constructor( endingBefore, financialAccountToken, pageSize, - result?.toImmutable(), + result, startingAfter, - status?.toImmutable(), + status, additionalHeaders.build(), additionalQueryParams.build(), ) @@ -381,9 +362,9 @@ private constructor( endingBefore?.let { put("ending_before", it) } financialAccountToken?.let { put("financial_account_token", it) } pageSize?.let { put("page_size", it.toString()) } - result?.let { put("result", it.joinToString(",") { it.toString() }) } + result?.let { put("result", it.toString()) } startingAfter?.let { put("starting_after", it) } - status?.let { put("status", it.joinToString(",") { it.toString() }) } + status?.let { put("status", it.toString()) } putAll(additionalQueryParams) } .build() @@ -585,6 +566,7 @@ private constructor( override fun toString() = value.toString() } + /** Filter by transaction result */ class Result @JsonCreator private constructor(private val value: JsonField) : Enum { /** @@ -710,6 +692,7 @@ private constructor( override fun toString() = value.toString() } + /** Filter by transaction status */ class Status @JsonCreator private constructor(private val value: JsonField) : Enum { /** @@ -730,14 +713,14 @@ private constructor( @JvmField val PENDING = of("PENDING") - @JvmField val SETTLED = of("SETTLED") - - @JvmField val VOIDED = of("VOIDED") - @JvmField val RETURNED = of("RETURNED") @JvmField val REVERSED = of("REVERSED") + @JvmField val SETTLED = of("SETTLED") + + @JvmField val VOIDED = of("VOIDED") + @JvmStatic fun of(value: String) = Status(JsonField.of(value)) } @@ -746,10 +729,10 @@ private constructor( DECLINED, EXPIRED, PENDING, - SETTLED, - VOIDED, RETURNED, REVERSED, + SETTLED, + VOIDED, } /** @@ -765,10 +748,10 @@ private constructor( DECLINED, EXPIRED, PENDING, - SETTLED, - VOIDED, RETURNED, REVERSED, + SETTLED, + VOIDED, /** An enum member indicating that [Status] was instantiated with an unknown value. */ _UNKNOWN, } @@ -785,10 +768,10 @@ private constructor( DECLINED -> Value.DECLINED EXPIRED -> Value.EXPIRED PENDING -> Value.PENDING - SETTLED -> Value.SETTLED - VOIDED -> Value.VOIDED RETURNED -> Value.RETURNED REVERSED -> Value.REVERSED + SETTLED -> Value.SETTLED + VOIDED -> Value.VOIDED else -> Value._UNKNOWN } @@ -806,10 +789,10 @@ private constructor( DECLINED -> Known.DECLINED EXPIRED -> Known.EXPIRED PENDING -> Known.PENDING - SETTLED -> Known.SETTLED - VOIDED -> Known.VOIDED RETURNED -> Known.RETURNED REVERSED -> Known.REVERSED + SETTLED -> Known.SETTLED + VOIDED -> Known.VOIDED else -> throw LithicInvalidDataException("Unknown Status: $value") } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ApplyParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ApplyParams.kt index 44946bf62..15d085c07 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ApplyParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ApplyParams.kt @@ -498,6 +498,7 @@ private constructor( class ApplyAuthRuleRequestAccountTokens private constructor( private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val additionalProperties: MutableMap, ) { @@ -505,17 +506,29 @@ private constructor( private constructor( @JsonProperty("account_tokens") @ExcludeMissing - accountTokens: JsonField> = JsonMissing.of() - ) : this(accountTokens, mutableMapOf()) + accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), + ) : this(accountTokens, businessAccountTokens, mutableMapOf()) /** * Account tokens to which the Auth Rule applies. * - * @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). + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun accountTokens(): Optional> = + accountTokens.getOptional("account_tokens") + + /** + * Business Account tokens to which the Auth Rule applies. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). */ - fun accountTokens(): List = accountTokens.getRequired("account_tokens") + fun businessAccountTokens(): Optional> = + businessAccountTokens.getOptional("business_account_tokens") /** * Returns the raw JSON value of [accountTokens]. @@ -527,6 +540,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -544,11 +567,6 @@ private constructor( /** * Returns a mutable builder for constructing an instance of * [ApplyAuthRuleRequestAccountTokens]. - * - * The following fields are required: - * ```java - * .accountTokens() - * ``` */ @JvmStatic fun builder() = Builder() } @@ -557,6 +575,7 @@ private constructor( class Builder internal constructor() { private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -565,6 +584,10 @@ private constructor( ) = apply { accountTokens = applyAuthRuleRequestAccountTokens.accountTokens.map { it.toMutableList() } + businessAccountTokens = + applyAuthRuleRequestAccountTokens.businessAccountTokens.map { + it.toMutableList() + } additionalProperties = applyAuthRuleRequestAccountTokens.additionalProperties.toMutableMap() } @@ -596,6 +619,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed + * `List` value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -622,17 +672,11 @@ private constructor( * Returns an immutable instance of [ApplyAuthRuleRequestAccountTokens]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .accountTokens() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): ApplyAuthRuleRequestAccountTokens = ApplyAuthRuleRequestAccountTokens( - checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + (accountTokens ?: JsonMissing.of()).map { it.toImmutable() }, + (businessAccountTokens ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toMutableMap(), ) } @@ -645,6 +689,7 @@ private constructor( } accountTokens() + businessAccountTokens() validated = true } @@ -663,7 +708,9 @@ private constructor( * Used for best match union deserialization. */ @JvmSynthetic - internal fun validity(): Int = (accountTokens.asKnown().getOrNull()?.size ?: 0) + internal fun validity(): Int = + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) override fun equals(other: Any?): Boolean { if (this === other) { @@ -672,15 +719,18 @@ private constructor( return other is ApplyAuthRuleRequestAccountTokens && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(accountTokens, additionalProperties) } + private val hashCode: Int by lazy { + Objects.hash(accountTokens, businessAccountTokens, additionalProperties) + } override fun hashCode(): Int = hashCode override fun toString() = - "ApplyAuthRuleRequestAccountTokens{accountTokens=$accountTokens, additionalProperties=$additionalProperties}" + "ApplyAuthRuleRequestAccountTokens{accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, additionalProperties=$additionalProperties}" } class ApplyAuthRuleRequestCardTokens diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2BacktestCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2BacktestCreateParams.kt index badd04900..00e4b9b98 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2BacktestCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2BacktestCreateParams.kt @@ -36,7 +36,7 @@ import kotlin.jvm.optionals.getOrNull * backtest reports on-demand through the * `/v2/auth_rules/{auth_rule_token}/backtests/{auth_rule_backtest_token}` endpoint. * - * Lithic currently supports backtesting for `CONDITIONAL_BLOCK` / `CONDITIONAL_3DS_ACTION` rules. + * Lithic currently supports backtesting for `CONDITIONAL_BLOCK` / `CONDITIONAL_ACTION` rules. * Backtesting for `VELOCITY_LIMIT` rules is generally not supported. In specific cases (i.e. where * Lithic has pre-calculated the requested velocity metrics for historical transactions), a backtest * may be feasible. However, such cases are uncommon and customers should not anticipate support for 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 1f7ae4040..9efad1fd0 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 @@ -482,6 +482,8 @@ private constructor( class CreateAuthRuleRequestAccountTokens private constructor( private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, + private val eventStream: JsonField, private val name: JsonField, private val parameters: JsonField, private val type: JsonField, @@ -493,6 +495,12 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("event_stream") + @ExcludeMissing + eventStream: JsonField = JsonMissing.of(), @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), @JsonProperty("parameters") @ExcludeMissing @@ -500,16 +508,41 @@ private constructor( @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), - ) : this(accountTokens, name, parameters, type, mutableMapOf()) + ) : this( + accountTokens, + businessAccountTokens, + eventStream, + name, + parameters, + type, + mutableMapOf(), + ) /** * Account tokens to which the Auth Rule applies. * - * @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). + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun accountTokens(): Optional> = + accountTokens.getOptional("account_tokens") + + /** + * Business Account tokens to which the Auth Rule applies. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun businessAccountTokens(): Optional> = + businessAccountTokens.getOptional("business_account_tokens") + + /** + * The event stream during which the rule will be evaluated. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). */ - fun accountTokens(): List = accountTokens.getRequired("account_tokens") + fun eventStream(): Optional = eventStream.getOptional("event_stream") /** * Auth Rule Name @@ -528,12 +561,13 @@ private constructor( fun parameters(): Optional = parameters.getOptional("parameters") /** - * The type of Auth Rule. Effectively determines the event stream during which it will - * be evaluated. + * 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 several + * event streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. * * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -550,6 +584,26 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + + /** + * Returns the raw JSON value of [eventStream]. + * + * Unlike [eventStream], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("event_stream") + @ExcludeMissing + fun _eventStream(): JsonField = eventStream + /** * Returns the raw JSON value of [name]. * @@ -591,11 +645,6 @@ private constructor( /** * Returns a mutable builder for constructing an instance of * [CreateAuthRuleRequestAccountTokens]. - * - * The following fields are required: - * ```java - * .accountTokens() - * ``` */ @JvmStatic fun builder() = Builder() } @@ -604,6 +653,8 @@ private constructor( class Builder internal constructor() { private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null + private var eventStream: JsonField = JsonMissing.of() private var name: JsonField = JsonMissing.of() private var parameters: JsonField = JsonMissing.of() private var type: JsonField = JsonMissing.of() @@ -615,6 +666,11 @@ private constructor( ) = apply { accountTokens = createAuthRuleRequestAccountTokens.accountTokens.map { it.toMutableList() } + businessAccountTokens = + createAuthRuleRequestAccountTokens.businessAccountTokens.map { + it.toMutableList() + } + eventStream = createAuthRuleRequestAccountTokens.eventStream name = createAuthRuleRequestAccountTokens.name parameters = createAuthRuleRequestAccountTokens.parameters type = createAuthRuleRequestAccountTokens.type @@ -649,6 +705,47 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed + * `List` value instead. This method is primarily for setting the field to + * an undocumented or not yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + + /** The event stream during which the rule will be evaluated. */ + fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) + + /** + * Sets [Builder.eventStream] to an arbitrary JSON value. + * + * You should usually call [Builder.eventStream] with a well-typed [EventStream] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun eventStream(eventStream: JsonField) = apply { + this.eventStream = eventStream + } + /** Auth Rule Name */ fun name(name: String?) = name(JsonField.ofNullable(name)) @@ -706,12 +803,26 @@ private constructor( parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) /** - * The type of Auth Rule. Effectively determines the event stream during which it - * will be evaluated. + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: + Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + + /** + * 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 + * several event streams, the effective one is defined by the separate + * `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -750,17 +861,12 @@ private constructor( * Returns an immutable instance of [CreateAuthRuleRequestAccountTokens]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .accountTokens() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): CreateAuthRuleRequestAccountTokens = CreateAuthRuleRequestAccountTokens( - checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + (accountTokens ?: JsonMissing.of()).map { it.toImmutable() }, + (businessAccountTokens ?: JsonMissing.of()).map { it.toImmutable() }, + eventStream, name, parameters, type, @@ -776,6 +882,8 @@ private constructor( } accountTokens() + businessAccountTokens() + eventStream().ifPresent { it.validate() } name() parameters().ifPresent { it.validate() } type().ifPresent { it.validate() } @@ -799,10 +907,145 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + + (eventStream.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + (parameters.asKnown().getOrNull()?.validity() ?: 0) + (type.asKnown().getOrNull()?.validity() ?: 0) + /** The event stream during which the rule will be evaluated. */ + class EventStream + @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") + + @JvmField val THREE_DS_AUTHENTICATION = of("THREE_DS_AUTHENTICATION") + + @JvmStatic fun of(value: String) = EventStream(JsonField.of(value)) + } + + /** An enum containing [EventStream]'s known values. */ + enum class Known { + AUTHORIZATION, + THREE_DS_AUTHENTICATION, + } + + /** + * An enum containing [EventStream]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [EventStream] 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, + THREE_DS_AUTHENTICATION, + /** + * An enum member indicating that [EventStream] 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 + THREE_DS_AUTHENTICATION -> Value.THREE_DS_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) { + AUTHORIZATION -> Known.AUTHORIZATION + THREE_DS_AUTHENTICATION -> Known.THREE_DS_AUTHENTICATION + else -> throw LithicInvalidDataException("Unknown EventStream: $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(): EventStream = 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 EventStream && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + /** Parameters for the Auth Rule */ @JsonDeserialize(using = Parameters.Deserializer::class) @JsonSerialize(using = Parameters.Serializer::class) @@ -812,6 +1055,9 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -827,6 +1073,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -835,6 +1085,9 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = + conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -847,6 +1100,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -857,6 +1113,10 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction( + conditionalAuthorizationAction + ) else -> visitor.unknown(_json) } @@ -890,6 +1150,13 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -928,6 +1195,11 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -941,7 +1213,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -950,6 +1223,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -960,6 +1234,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -982,6 +1258,11 @@ private constructor( fun ofConditional3dsAction( conditional3dsAction: Conditional3dsActionParameters ) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1000,6 +1281,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1040,6 +1325,18 @@ private constructor( ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef< + ConditionalAuthorizationActionParameters + >(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1073,71 +1370,1533 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } - } - /** - * The type of Auth Rule. Effectively determines the event stream during which it will - * be evaluated. - * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. - * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. - * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. - */ - class AuthRuleType - @JsonCreator - private constructor(private val value: JsonField) : Enum { + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) - /** - * 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 + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") - companion object { + /** + * @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 conditions(): List = conditions.getRequired("conditions") - @JvmField val CONDITIONAL_BLOCK = of("CONDITIONAL_BLOCK") + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("action") + @ExcludeMissing + fun _action(): JsonField = action - @JvmField val VELOCITY_LIMIT = of("VELOCITY_LIMIT") + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions - @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } - @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) - } + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } - /** An enum containing [AuthRuleType]'s known values. */ - enum class Known { - CONDITIONAL_BLOCK, - VELOCITY_LIMIT, - MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, - } + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } - /** - * An enum containing [AuthRuleType]'s known values, as well as an [_UNKNOWN] - * member. - * - * An instance of [AuthRuleType] 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 { + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 + * [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("value") + @ExcludeMissing + fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: + * (1) all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and + * (3) ANT for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to + * the issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary + * account number (PAN) was entered. Valid values are `AUTO_ENTRY`, + * `BAR_CODE`, `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, + * `ERROR_MAGNETIC_STRIPE`, `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, + * `MANUAL`, `OCR`, `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, + * `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus + * the acquirer fee field in the settlement/cardholder billing + * currency. This is the amount the issuer should authorize against + * unless the issuer is paying the acquirer fee on behalf of the + * cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level + * associated with a given authorization. Scores are on a range of + * 0-999, with 0 representing the lowest risk and 999 representing the + * highest risk. For Visa transactions, where the raw score has a + * range of 0-99, Lithic will normalize the score by multiplying the + * raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the + * card in the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card + * in the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the + * card in the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, + * indicates the source of the token. Valid values are `APPLE_PAY`, + * `GOOGLE_PAY`, `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, + * `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed + * [Attribute] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed + * [Operation] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with + * `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException( + "Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField + val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException( + "Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> + visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings( + listOfStrings: List + ) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings( + listOfStrings: List + ) = listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = + Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or + * `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a + * value of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or + * `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { Value(regex = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { + Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } + } + + /** + * 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 several + * event streams, the effective one is defined by the separate `event_stream` field. + * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. + * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. + * - `MERCHANT_LOCK`: AUTHORIZATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. + */ + class AuthRuleType + @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 CONDITIONAL_BLOCK = of("CONDITIONAL_BLOCK") + + @JvmField val VELOCITY_LIMIT = of("VELOCITY_LIMIT") + + @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") + + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") + + @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) + } + + /** An enum containing [AuthRuleType]'s known values. */ + enum class Known { + CONDITIONAL_BLOCK, + VELOCITY_LIMIT, + MERCHANT_LOCK, + CONDITIONAL_ACTION, + } + + /** + * An enum containing [AuthRuleType]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [AuthRuleType] 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 { CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -1157,7 +2916,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1175,7 +2934,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -1240,6 +2999,8 @@ private constructor( return other is CreateAuthRuleRequestAccountTokens && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && + eventStream == other.eventStream && name == other.name && parameters == other.parameters && type == other.type && @@ -1247,18 +3008,27 @@ private constructor( } private val hashCode: Int by lazy { - Objects.hash(accountTokens, name, parameters, type, additionalProperties) + Objects.hash( + accountTokens, + businessAccountTokens, + eventStream, + name, + parameters, + type, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "CreateAuthRuleRequestAccountTokens{accountTokens=$accountTokens, name=$name, parameters=$parameters, type=$type, additionalProperties=$additionalProperties}" + "CreateAuthRuleRequestAccountTokens{accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, eventStream=$eventStream, name=$name, parameters=$parameters, type=$type, additionalProperties=$additionalProperties}" } class CreateAuthRuleRequestCardTokens private constructor( private val cardTokens: JsonField>, + private val eventStream: JsonField, private val name: JsonField, private val parameters: JsonField, private val type: JsonField, @@ -1270,6 +3040,9 @@ private constructor( @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), + @JsonProperty("event_stream") + @ExcludeMissing + eventStream: JsonField = JsonMissing.of(), @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), @JsonProperty("parameters") @ExcludeMissing @@ -1277,7 +3050,7 @@ private constructor( @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), - ) : this(cardTokens, name, parameters, type, mutableMapOf()) + ) : this(cardTokens, eventStream, name, parameters, type, mutableMapOf()) /** * Card tokens to which the Auth Rule applies. @@ -1288,6 +3061,14 @@ private constructor( */ fun cardTokens(): List = cardTokens.getRequired("card_tokens") + /** + * The event stream during which the rule will be evaluated. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun eventStream(): Optional = eventStream.getOptional("event_stream") + /** * Auth Rule Name * @@ -1305,12 +3086,13 @@ private constructor( fun parameters(): Optional = parameters.getOptional("parameters") /** - * The type of Auth Rule. Effectively determines the event stream during which it will - * be evaluated. + * 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 several + * event streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. * * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -1327,6 +3109,16 @@ private constructor( @ExcludeMissing fun _cardTokens(): JsonField> = cardTokens + /** + * Returns the raw JSON value of [eventStream]. + * + * Unlike [eventStream], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("event_stream") + @ExcludeMissing + fun _eventStream(): JsonField = eventStream + /** * Returns the raw JSON value of [name]. * @@ -1381,6 +3173,7 @@ private constructor( class Builder internal constructor() { private var cardTokens: JsonField>? = null + private var eventStream: JsonField = JsonMissing.of() private var name: JsonField = JsonMissing.of() private var parameters: JsonField = JsonMissing.of() private var type: JsonField = JsonMissing.of() @@ -1392,6 +3185,7 @@ private constructor( ) = apply { cardTokens = createAuthRuleRequestCardTokens.cardTokens.map { it.toMutableList() } + eventStream = createAuthRuleRequestCardTokens.eventStream name = createAuthRuleRequestCardTokens.name parameters = createAuthRuleRequestCardTokens.parameters type = createAuthRuleRequestCardTokens.type @@ -1425,6 +3219,20 @@ private constructor( } } + /** The event stream during which the rule will be evaluated. */ + fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) + + /** + * Sets [Builder.eventStream] to an arbitrary JSON value. + * + * You should usually call [Builder.eventStream] with a well-typed [EventStream] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun eventStream(eventStream: JsonField) = apply { + this.eventStream = eventStream + } + /** Auth Rule Name */ fun name(name: String?) = name(JsonField.ofNullable(name)) @@ -1482,12 +3290,26 @@ private constructor( parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) /** - * The type of Auth Rule. Effectively determines the event stream during which it - * will be evaluated. + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: + Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + + /** + * 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 + * several event streams, the effective one is defined by the separate + * `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -1537,6 +3359,7 @@ private constructor( fun build(): CreateAuthRuleRequestCardTokens = CreateAuthRuleRequestCardTokens( checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, + eventStream, name, parameters, type, @@ -1552,6 +3375,7 @@ private constructor( } cardTokens() + eventStream().ifPresent { it.validate() } name() parameters().ifPresent { it.validate() } type().ifPresent { it.validate() } @@ -1575,26 +3399,163 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (cardTokens.asKnown().getOrNull()?.size ?: 0) + + (eventStream.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) + (parameters.asKnown().getOrNull()?.validity() ?: 0) + (type.asKnown().getOrNull()?.validity() ?: 0) - /** Parameters for the Auth Rule */ - @JsonDeserialize(using = Parameters.Deserializer::class) - @JsonSerialize(using = Parameters.Serializer::class) - class Parameters - private constructor( - private val conditionalBlock: ConditionalBlockParameters? = null, - private val velocityLimitParams: VelocityLimitParams? = null, - private val merchantLock: MerchantLockParameters? = null, - private val conditional3dsAction: Conditional3dsActionParameters? = null, - private val _json: JsonValue? = null, - ) { - - fun conditionalBlock(): Optional = - Optional.ofNullable(conditionalBlock) + /** The event stream during which the rule will be evaluated. */ + class EventStream + @JsonCreator + private constructor(private val value: JsonField) : Enum { - fun velocityLimitParams(): Optional = + /** + * 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") + + @JvmField val THREE_DS_AUTHENTICATION = of("THREE_DS_AUTHENTICATION") + + @JvmStatic fun of(value: String) = EventStream(JsonField.of(value)) + } + + /** An enum containing [EventStream]'s known values. */ + enum class Known { + AUTHORIZATION, + THREE_DS_AUTHENTICATION, + } + + /** + * An enum containing [EventStream]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [EventStream] 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, + THREE_DS_AUTHENTICATION, + /** + * An enum member indicating that [EventStream] 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 + THREE_DS_AUTHENTICATION -> Value.THREE_DS_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) { + AUTHORIZATION -> Known.AUTHORIZATION + THREE_DS_AUTHENTICATION -> Known.THREE_DS_AUTHENTICATION + else -> throw LithicInvalidDataException("Unknown EventStream: $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(): EventStream = 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 EventStream && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** Parameters for the Auth Rule */ + @JsonDeserialize(using = Parameters.Deserializer::class) + @JsonSerialize(using = Parameters.Serializer::class) + class Parameters + private constructor( + private val conditionalBlock: ConditionalBlockParameters? = null, + private val velocityLimitParams: VelocityLimitParams? = null, + private val merchantLock: MerchantLockParameters? = null, + private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters? = + null, + private val _json: JsonValue? = null, + ) { + + fun conditionalBlock(): Optional = + Optional.ofNullable(conditionalBlock) + + fun velocityLimitParams(): Optional = Optional.ofNullable(velocityLimitParams) fun merchantLock(): Optional = @@ -1603,6 +3564,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1611,6 +3576,9 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = + conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1623,6 +3591,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1633,6 +3604,10 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction( + conditionalAuthorizationAction + ) else -> visitor.unknown(_json) } @@ -1666,6 +3641,13 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1704,6 +3686,11 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1717,7 +3704,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1726,6 +3714,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1736,6 +3725,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1758,6 +3749,11 @@ private constructor( fun ofConditional3dsAction( conditional3dsAction: Conditional3dsActionParameters ) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1776,6 +3772,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1816,6 +3816,18 @@ private constructor( ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef< + ConditionalAuthorizationActionParameters + >(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1849,20 +3861,1482 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("action") + @ExcludeMissing + fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 + * [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("value") + @ExcludeMissing + fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: + * (1) all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and + * (3) ANT for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to + * the issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary + * account number (PAN) was entered. Valid values are `AUTO_ENTRY`, + * `BAR_CODE`, `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, + * `ERROR_MAGNETIC_STRIPE`, `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, + * `MANUAL`, `OCR`, `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, + * `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus + * the acquirer fee field in the settlement/cardholder billing + * currency. This is the amount the issuer should authorize against + * unless the issuer is paying the acquirer fee on behalf of the + * cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level + * associated with a given authorization. Scores are on a range of + * 0-999, with 0 representing the lowest risk and 999 representing the + * highest risk. For Visa transactions, where the raw score has a + * range of 0-99, Lithic will normalize the score by multiplying the + * raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the + * card in the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card + * in the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the + * card in the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, + * indicates the source of the token. Valid values are `APPLE_PAY`, + * `GOOGLE_PAY`, `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, + * `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed + * [Attribute] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed + * [Operation] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with + * `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException( + "Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField + val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException( + "Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> + visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings( + listOfStrings: List + ) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings( + listOfStrings: List + ) = listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = + Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or + * `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a + * value of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or + * `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { Value(regex = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { + Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } /** - * The type of Auth Rule. Effectively determines the event stream during which it will - * be evaluated. + * 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 several + * event streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator @@ -1886,7 +5360,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1896,7 +5370,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1913,7 +5387,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -1933,7 +5407,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1951,7 +5425,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2016,6 +5490,7 @@ private constructor( return other is CreateAuthRuleRequestCardTokens && cardTokens == other.cardTokens && + eventStream == other.eventStream && name == other.name && parameters == other.parameters && type == other.type && @@ -2023,18 +5498,19 @@ private constructor( } private val hashCode: Int by lazy { - Objects.hash(cardTokens, name, parameters, type, additionalProperties) + Objects.hash(cardTokens, eventStream, name, parameters, type, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "CreateAuthRuleRequestCardTokens{cardTokens=$cardTokens, name=$name, parameters=$parameters, type=$type, additionalProperties=$additionalProperties}" + "CreateAuthRuleRequestCardTokens{cardTokens=$cardTokens, eventStream=$eventStream, name=$name, parameters=$parameters, type=$type, additionalProperties=$additionalProperties}" } class CreateAuthRuleRequestProgramLevel private constructor( private val programLevel: JsonField, + private val eventStream: JsonField, private val excludedCardTokens: JsonField>, private val name: JsonField, private val parameters: JsonField, @@ -2047,6 +5523,9 @@ private constructor( @JsonProperty("program_level") @ExcludeMissing programLevel: JsonField = JsonMissing.of(), + @JsonProperty("event_stream") + @ExcludeMissing + eventStream: JsonField = JsonMissing.of(), @JsonProperty("excluded_card_tokens") @ExcludeMissing excludedCardTokens: JsonField> = JsonMissing.of(), @@ -2057,7 +5536,15 @@ private constructor( @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), - ) : this(programLevel, excludedCardTokens, name, parameters, type, mutableMapOf()) + ) : this( + programLevel, + eventStream, + excludedCardTokens, + name, + parameters, + type, + mutableMapOf(), + ) /** * Whether the Auth Rule applies to all authorizations on the card program. @@ -2068,6 +5555,14 @@ private constructor( */ fun programLevel(): Boolean = programLevel.getRequired("program_level") + /** + * The event stream during which the rule will be evaluated. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun eventStream(): Optional = eventStream.getOptional("event_stream") + /** * Card tokens to which the Auth Rule does not apply. * @@ -2094,12 +5589,13 @@ private constructor( fun parameters(): Optional = parameters.getOptional("parameters") /** - * The type of Auth Rule. Effectively determines the event stream during which it will - * be evaluated. + * 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 several + * event streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. * * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -2116,6 +5612,16 @@ private constructor( @ExcludeMissing fun _programLevel(): JsonField = programLevel + /** + * Returns the raw JSON value of [eventStream]. + * + * Unlike [eventStream], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("event_stream") + @ExcludeMissing + fun _eventStream(): JsonField = eventStream + /** * Returns the raw JSON value of [excludedCardTokens]. * @@ -2180,6 +5686,7 @@ private constructor( class Builder internal constructor() { private var programLevel: JsonField? = null + private var eventStream: JsonField = JsonMissing.of() private var excludedCardTokens: JsonField>? = null private var name: JsonField = JsonMissing.of() private var parameters: JsonField = JsonMissing.of() @@ -2191,6 +5698,7 @@ private constructor( createAuthRuleRequestProgramLevel: CreateAuthRuleRequestProgramLevel ) = apply { programLevel = createAuthRuleRequestProgramLevel.programLevel + eventStream = createAuthRuleRequestProgramLevel.eventStream excludedCardTokens = createAuthRuleRequestProgramLevel.excludedCardTokens.map { it.toMutableList() @@ -2216,6 +5724,20 @@ private constructor( this.programLevel = programLevel } + /** The event stream during which the rule will be evaluated. */ + fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) + + /** + * Sets [Builder.eventStream] to an arbitrary JSON value. + * + * You should usually call [Builder.eventStream] with a well-typed [EventStream] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun eventStream(eventStream: JsonField) = apply { + this.eventStream = eventStream + } + /** Card tokens to which the Auth Rule does not apply. */ fun excludedCardTokens(excludedCardTokens: List) = excludedCardTokens(JsonField.of(excludedCardTokens)) @@ -2300,12 +5822,26 @@ private constructor( parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) /** - * The type of Auth Rule. Effectively determines the event stream during which it - * will be evaluated. + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: + Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + + /** + * 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 + * several event streams, the effective one is defined by the separate + * `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -2355,6 +5891,7 @@ private constructor( fun build(): CreateAuthRuleRequestProgramLevel = CreateAuthRuleRequestProgramLevel( checkRequired("programLevel", programLevel), + eventStream, (excludedCardTokens ?: JsonMissing.of()).map { it.toImmutable() }, name, parameters, @@ -2363,42 +5900,177 @@ private constructor( ) } - private var validated: Boolean = false + private var validated: Boolean = false + + fun validate(): CreateAuthRuleRequestProgramLevel = apply { + if (validated) { + return@apply + } + + programLevel() + eventStream().ifPresent { it.validate() } + excludedCardTokens() + name() + parameters().ifPresent { it.validate() } + type().ifPresent { 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 (programLevel.asKnown().isPresent) 1 else 0) + + (eventStream.asKnown().getOrNull()?.validity() ?: 0) + + (excludedCardTokens.asKnown().getOrNull()?.size ?: 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (parameters.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + /** The event stream during which the rule will be evaluated. */ + class EventStream + @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") + + @JvmField val THREE_DS_AUTHENTICATION = of("THREE_DS_AUTHENTICATION") + + @JvmStatic fun of(value: String) = EventStream(JsonField.of(value)) + } + + /** An enum containing [EventStream]'s known values. */ + enum class Known { + AUTHORIZATION, + THREE_DS_AUTHENTICATION, + } + + /** + * An enum containing [EventStream]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [EventStream] 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, + THREE_DS_AUTHENTICATION, + /** + * An enum member indicating that [EventStream] 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 + THREE_DS_AUTHENTICATION -> Value.THREE_DS_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) { + AUTHORIZATION -> Known.AUTHORIZATION + THREE_DS_AUTHENTICATION -> Known.THREE_DS_AUTHENTICATION + else -> throw LithicInvalidDataException("Unknown EventStream: $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(): EventStream = apply { + if (validated) { + return@apply + } - fun validate(): CreateAuthRuleRequestProgramLevel = apply { - if (validated) { - return@apply + known() + validated = true } - programLevel() - excludedCardTokens() - name() - parameters().ifPresent { it.validate() } - type().ifPresent { it.validate() } - validated = true - } + fun isValid(): Boolean = + try { + validate() + true + } catch (e: LithicInvalidDataException) { + false + } - 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 EventStream && value == other.value } - /** - * 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 (programLevel.asKnown().isPresent) 1 else 0) + - (excludedCardTokens.asKnown().getOrNull()?.size ?: 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (parameters.asKnown().getOrNull()?.validity() ?: 0) + - (type.asKnown().getOrNull()?.validity() ?: 0) + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } /** Parameters for the Auth Rule */ @JsonDeserialize(using = Parameters.Deserializer::class) @@ -2409,6 +6081,9 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -2424,6 +6099,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -2432,6 +6111,9 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = + conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -2444,6 +6126,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -2454,6 +6139,10 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction( + conditionalAuthorizationAction + ) else -> visitor.unknown(_json) } @@ -2487,6 +6176,13 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -2525,6 +6221,11 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: + ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -2538,7 +6239,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -2547,6 +6249,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -2557,6 +6260,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -2579,6 +6284,11 @@ private constructor( fun ofConditional3dsAction( conditional3dsAction: Conditional3dsActionParameters ) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -2597,6 +6307,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -2637,6 +6351,18 @@ private constructor( ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef< + ConditionalAuthorizationActionParameters + >(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -2670,20 +6396,1482 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("action") + @ExcludeMissing + fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a + * non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 + * [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("value") + @ExcludeMissing + fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: + * (1) all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and + * (3) ANT for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to + * the issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary + * account number (PAN) was entered. Valid values are `AUTO_ENTRY`, + * `BAR_CODE`, `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, + * `ERROR_MAGNETIC_STRIPE`, `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, + * `MANUAL`, `OCR`, `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, + * `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus + * the acquirer fee field in the settlement/cardholder billing + * currency. This is the amount the issuer should authorize against + * unless the issuer is paying the acquirer fee on behalf of the + * cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level + * associated with a given authorization. Scores are on a range of + * 0-999, with 0 representing the lowest risk and 999 representing the + * highest risk. For Visa transactions, where the raw score has a + * range of 0-99, Lithic will normalize the score by multiplying the + * raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the + * card in the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card + * in the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the + * card in the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, + * indicates the source of the token. Valid values are `APPLE_PAY`, + * `GOOGLE_PAY`, `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, + * `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed + * [Attribute] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed + * [Operation] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with + * `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned + * instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException( + "Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField + val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an + * [_UNKNOWN] member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException( + "Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> + visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings( + listOfStrings: List + ) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings( + listOfStrings: List + ) = listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = + Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or + * `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a + * value of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or + * `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef()) + ?.let { Value(regex = it, _json = json) }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { + Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } /** - * The type of Auth Rule. Effectively determines the event stream during which it will - * be evaluated. + * 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 several + * event streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator @@ -2707,7 +7895,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -2717,7 +7905,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -2734,7 +7922,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an * unknown value. @@ -2754,7 +7942,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -2772,7 +7960,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2837,6 +8025,7 @@ private constructor( return other is CreateAuthRuleRequestProgramLevel && programLevel == other.programLevel && + eventStream == other.eventStream && excludedCardTokens == other.excludedCardTokens && name == other.name && parameters == other.parameters && @@ -2847,6 +8036,7 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( programLevel, + eventStream, excludedCardTokens, name, parameters, @@ -2858,7 +8048,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "CreateAuthRuleRequestProgramLevel{programLevel=$programLevel, excludedCardTokens=$excludedCardTokens, name=$name, parameters=$parameters, type=$type, additionalProperties=$additionalProperties}" + "CreateAuthRuleRequestProgramLevel{programLevel=$programLevel, eventStream=$eventStream, excludedCardTokens=$excludedCardTokens, name=$name, parameters=$parameters, type=$type, additionalProperties=$additionalProperties}" } } 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 9269adfdb..ece31078d 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 @@ -15,15 +15,19 @@ 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.Params import com.lithic.api.core.allMaxBy +import com.lithic.api.core.checkKnown +import com.lithic.api.core.checkRequired import com.lithic.api.core.getOrThrow import com.lithic.api.core.http.Headers import com.lithic.api.core.http.QueryParams +import com.lithic.api.core.toImmutable import com.lithic.api.errors.LithicInvalidDataException import java.util.Collections import java.util.Objects @@ -153,6 +157,14 @@ private constructor( body.parameters(conditional3dsAction) } + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = apply { body.parameters(conditionalAuthorizationAction) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { body.additionalProperties(additionalBodyProperties) } @@ -398,6 +410,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -480,6 +503,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -494,6 +519,9 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -502,6 +530,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -513,6 +543,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -522,6 +555,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -555,6 +590,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -593,6 +634,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -606,11 +651,18 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = - Objects.hash(conditionalBlock, velocityLimitParams, merchantLock, conditional3dsAction) + Objects.hash( + conditionalBlock, + velocityLimitParams, + merchantLock, + conditional3dsAction, + conditionalAuthorizationAction, + ) override fun toString(): String = when { @@ -620,6 +672,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -641,6 +695,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -656,6 +715,10 @@ private constructor( fun visitConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -688,6 +751,13 @@ private constructor( }, tryDeserialize(node, jacksonTypeRef()) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters(conditionalAuthorizationAction = it, _json = json) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -719,11 +789,1404 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties.toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify a + * business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all ISO + * 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for Netherlands + * Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency of + * the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the issuer + * applies to the transaction. Valid values are `NONE`, `3DS_AUTHENTICATED`, or + * `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account number + * (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, `CONTACTLESS`, + * `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, `KEY_ENTERED`, + * `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, `UNSPECIFIED`, + * `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer + * fee field in the settlement/cardholder billing currency. This is the amount the + * issuer should authorize against unless the issuer is paying the acquirer fee on + * behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing the + * lowest risk and 999 representing the highest risk. For Visa transactions, where + * the raw score has a range of 0-99, Lithic will normalize the score by + * multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the transaction. + * Valid values are `CLOSED`, `OPEN`, `PAUSED`, `PENDING_ACTIVATION`, + * `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, `SAMSUNG_PAY`, + * `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction indicates + * the source of the token. Valid values are `CARDHOLDER`, `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. + * if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Condition]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition(attribute, operation, value, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify a + * business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all ISO + * 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for Netherlands + * Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency of + * the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the issuer + * applies to the transaction. Valid values are `NONE`, `3DS_AUTHENTICATED`, or + * `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account number + * (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, `CONTACTLESS`, + * `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, `KEY_ENTERED`, + * `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, `UNSPECIFIED`, + * `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the acquirer + * fee field in the settlement/cardholder billing currency. This is the amount the + * issuer should authorize against unless the issuer is paying the acquirer fee on + * behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing the + * lowest risk and 999 representing the highest risk. For Visa transactions, where + * the raw score has a range of 0-99, Lithic will normalize the score by + * multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the transaction. + * Valid values are `CLOSED`, `OPEN`, `PAUSED`, `PENDING_ACTIVATION`, + * `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, `SAMSUNG_PAY`, + * `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction indicates + * the source of the token. Valid values are `CARDHOLDER`, `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, `IS_GREATER_THAN_OR_EQUAL_TO`, + * `IS_LESS_THAN`, `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or + * `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, `IS_GREATER_THAN_OR_EQUAL_TO`, + * `IS_LESS_THAN`, `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or + * `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value of + * type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ListParams.kt index c016d72ed..fd29f1ce5 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2ListParams.kt @@ -17,6 +17,7 @@ import kotlin.jvm.optionals.getOrNull class AuthRuleV2ListParams private constructor( private val accountToken: String?, + private val businessAccountToken: String?, private val cardToken: String?, private val endingBefore: String?, private val eventStream: EventStream?, @@ -30,6 +31,9 @@ private constructor( /** Only return Auth Rules that are bound to the provided account token. */ fun accountToken(): Optional = Optional.ofNullable(accountToken) + /** Only return Auth Rules that are bound to the provided business account token. */ + fun businessAccountToken(): Optional = Optional.ofNullable(businessAccountToken) + /** Only return Auth Rules that are bound to the provided card token. */ fun cardToken(): Optional = Optional.ofNullable(cardToken) @@ -74,6 +78,7 @@ private constructor( class Builder internal constructor() { private var accountToken: String? = null + private var businessAccountToken: String? = null private var cardToken: String? = null private var endingBefore: String? = null private var eventStream: EventStream? = null @@ -86,6 +91,7 @@ private constructor( @JvmSynthetic internal fun from(authRuleV2ListParams: AuthRuleV2ListParams) = apply { accountToken = authRuleV2ListParams.accountToken + businessAccountToken = authRuleV2ListParams.businessAccountToken cardToken = authRuleV2ListParams.cardToken endingBefore = authRuleV2ListParams.endingBefore eventStream = authRuleV2ListParams.eventStream @@ -102,6 +108,18 @@ private constructor( /** Alias for calling [Builder.accountToken] with `accountToken.orElse(null)`. */ fun accountToken(accountToken: Optional) = accountToken(accountToken.getOrNull()) + /** Only return Auth Rules that are bound to the provided business account token. */ + fun businessAccountToken(businessAccountToken: String?) = apply { + this.businessAccountToken = businessAccountToken + } + + /** + * Alias for calling [Builder.businessAccountToken] with + * `businessAccountToken.orElse(null)`. + */ + fun businessAccountToken(businessAccountToken: Optional) = + businessAccountToken(businessAccountToken.getOrNull()) + /** Only return Auth Rules that are bound to the provided card token. */ fun cardToken(cardToken: String?) = apply { this.cardToken = cardToken } @@ -258,6 +276,7 @@ private constructor( fun build(): AuthRuleV2ListParams = AuthRuleV2ListParams( accountToken, + businessAccountToken, cardToken, endingBefore, eventStream, @@ -275,6 +294,7 @@ private constructor( QueryParams.builder() .apply { accountToken?.let { put("account_token", it) } + businessAccountToken?.let { put("business_account_token", it) } cardToken?.let { put("card_token", it) } endingBefore?.let { put("ending_before", it) } eventStream?.let { put("event_stream", it.toString()) } @@ -433,6 +453,8 @@ private constructor( @JvmField val ACCOUNT = of("ACCOUNT") + @JvmField val BUSINESS_ACCOUNT = of("BUSINESS_ACCOUNT") + @JvmField val CARD = of("CARD") @JvmField val ANY = of("ANY") @@ -444,6 +466,7 @@ private constructor( enum class Known { PROGRAM, ACCOUNT, + BUSINESS_ACCOUNT, CARD, ANY, } @@ -460,6 +483,7 @@ private constructor( enum class Value { PROGRAM, ACCOUNT, + BUSINESS_ACCOUNT, CARD, ANY, /** An enum member indicating that [Scope] was instantiated with an unknown value. */ @@ -477,6 +501,7 @@ private constructor( when (this) { PROGRAM -> Value.PROGRAM ACCOUNT -> Value.ACCOUNT + BUSINESS_ACCOUNT -> Value.BUSINESS_ACCOUNT CARD -> Value.CARD ANY -> Value.ANY else -> Value._UNKNOWN @@ -495,6 +520,7 @@ private constructor( when (this) { PROGRAM -> Known.PROGRAM ACCOUNT -> Known.ACCOUNT + BUSINESS_ACCOUNT -> Known.BUSINESS_ACCOUNT CARD -> Known.CARD ANY -> Known.ANY else -> throw LithicInvalidDataException("Unknown Scope: $value") @@ -559,6 +585,7 @@ private constructor( return other is AuthRuleV2ListParams && accountToken == other.accountToken && + businessAccountToken == other.businessAccountToken && cardToken == other.cardToken && endingBefore == other.endingBefore && eventStream == other.eventStream && @@ -572,6 +599,7 @@ private constructor( override fun hashCode(): Int = Objects.hash( accountToken, + businessAccountToken, cardToken, endingBefore, eventStream, @@ -583,5 +611,5 @@ private constructor( ) override fun toString() = - "AuthRuleV2ListParams{accountToken=$accountToken, cardToken=$cardToken, endingBefore=$endingBefore, eventStream=$eventStream, pageSize=$pageSize, scope=$scope, startingAfter=$startingAfter, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" + "AuthRuleV2ListParams{accountToken=$accountToken, businessAccountToken=$businessAccountToken, cardToken=$cardToken, endingBefore=$endingBefore, eventStream=$eventStream, pageSize=$pageSize, scope=$scope, startingAfter=$startingAfter, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2UpdateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2UpdateParams.kt index 4da42cbb9..35dd411c2 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2UpdateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthRuleV2UpdateParams.kt @@ -97,9 +97,11 @@ private constructor( fun body(body: Body) = apply { this.body = body } - /** Alias for calling [body] with `Body.ofAccountLevelRule(accountLevelRule)`. */ - fun body(accountLevelRule: Body.AccountLevelRule) = - body(Body.ofAccountLevelRule(accountLevelRule)) + /** Alias for calling [body] with `Body.ofUnionMember0(unionMember0)`. */ + fun body(unionMember0: Body.UnionMember0) = body(Body.ofUnionMember0(unionMember0)) + + /** Alias for calling [body] with `Body.ofUnionMember1(unionMember1)`. */ + fun body(unionMember1: Body.UnionMember1) = body(Body.ofUnionMember1(unionMember1)) /** Alias for calling [body] with `Body.ofCardLevelRule(cardLevelRule)`. */ fun body(cardLevelRule: Body.CardLevelRule) = body(Body.ofCardLevelRule(cardLevelRule)) @@ -243,25 +245,32 @@ private constructor( @JsonSerialize(using = Body.Serializer::class) class Body private constructor( - private val accountLevelRule: AccountLevelRule? = null, + private val unionMember0: UnionMember0? = null, + private val unionMember1: UnionMember1? = null, private val cardLevelRule: CardLevelRule? = null, private val programLevelRule: ProgramLevelRule? = null, private val _json: JsonValue? = null, ) { - fun accountLevelRule(): Optional = Optional.ofNullable(accountLevelRule) + fun unionMember0(): Optional = Optional.ofNullable(unionMember0) + + fun unionMember1(): Optional = Optional.ofNullable(unionMember1) fun cardLevelRule(): Optional = Optional.ofNullable(cardLevelRule) fun programLevelRule(): Optional = Optional.ofNullable(programLevelRule) - fun isAccountLevelRule(): Boolean = accountLevelRule != null + fun isUnionMember0(): Boolean = unionMember0 != null + + fun isUnionMember1(): Boolean = unionMember1 != null fun isCardLevelRule(): Boolean = cardLevelRule != null fun isProgramLevelRule(): Boolean = programLevelRule != null - fun asAccountLevelRule(): AccountLevelRule = accountLevelRule.getOrThrow("accountLevelRule") + fun asUnionMember0(): UnionMember0 = unionMember0.getOrThrow("unionMember0") + + fun asUnionMember1(): UnionMember1 = unionMember1.getOrThrow("unionMember1") fun asCardLevelRule(): CardLevelRule = cardLevelRule.getOrThrow("cardLevelRule") @@ -271,7 +280,8 @@ private constructor( fun accept(visitor: Visitor): T = when { - accountLevelRule != null -> visitor.visitAccountLevelRule(accountLevelRule) + unionMember0 != null -> visitor.visitUnionMember0(unionMember0) + unionMember1 != null -> visitor.visitUnionMember1(unionMember1) cardLevelRule != null -> visitor.visitCardLevelRule(cardLevelRule) programLevelRule != null -> visitor.visitProgramLevelRule(programLevelRule) else -> visitor.unknown(_json) @@ -286,8 +296,12 @@ private constructor( accept( object : Visitor { - override fun visitAccountLevelRule(accountLevelRule: AccountLevelRule) { - accountLevelRule.validate() + override fun visitUnionMember0(unionMember0: UnionMember0) { + unionMember0.validate() + } + + override fun visitUnionMember1(unionMember1: UnionMember1) { + unionMember1.validate() } override fun visitCardLevelRule(cardLevelRule: CardLevelRule) { @@ -320,8 +334,11 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitAccountLevelRule(accountLevelRule: AccountLevelRule) = - accountLevelRule.validity() + override fun visitUnionMember0(unionMember0: UnionMember0) = + unionMember0.validity() + + override fun visitUnionMember1(unionMember1: UnionMember1) = + unionMember1.validity() override fun visitCardLevelRule(cardLevelRule: CardLevelRule) = cardLevelRule.validity() @@ -339,17 +356,19 @@ private constructor( } return other is Body && - accountLevelRule == other.accountLevelRule && + unionMember0 == other.unionMember0 && + unionMember1 == other.unionMember1 && cardLevelRule == other.cardLevelRule && programLevelRule == other.programLevelRule } override fun hashCode(): Int = - Objects.hash(accountLevelRule, cardLevelRule, programLevelRule) + Objects.hash(unionMember0, unionMember1, cardLevelRule, programLevelRule) override fun toString(): String = when { - accountLevelRule != null -> "Body{accountLevelRule=$accountLevelRule}" + unionMember0 != null -> "Body{unionMember0=$unionMember0}" + unionMember1 != null -> "Body{unionMember1=$unionMember1}" cardLevelRule != null -> "Body{cardLevelRule=$cardLevelRule}" programLevelRule != null -> "Body{programLevelRule=$programLevelRule}" _json != null -> "Body{_unknown=$_json}" @@ -359,8 +378,10 @@ private constructor( companion object { @JvmStatic - fun ofAccountLevelRule(accountLevelRule: AccountLevelRule) = - Body(accountLevelRule = accountLevelRule) + fun ofUnionMember0(unionMember0: UnionMember0) = Body(unionMember0 = unionMember0) + + @JvmStatic + fun ofUnionMember1(unionMember1: UnionMember1) = Body(unionMember1 = unionMember1) @JvmStatic fun ofCardLevelRule(cardLevelRule: CardLevelRule) = Body(cardLevelRule = cardLevelRule) @@ -373,7 +394,9 @@ private constructor( /** An interface that defines how to map each variant of [Body] to a value of type [T]. */ interface Visitor { - fun visitAccountLevelRule(accountLevelRule: AccountLevelRule): T + fun visitUnionMember0(unionMember0: UnionMember0): T + + fun visitUnionMember1(unionMember1: UnionMember1): T fun visitCardLevelRule(cardLevelRule: CardLevelRule): T @@ -400,8 +423,11 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Body(accountLevelRule = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + Body(unionMember0 = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Body(unionMember1 = it, _json = json) }, tryDeserialize(node, jacksonTypeRef())?.let { Body(cardLevelRule = it, _json = json) @@ -434,7 +460,8 @@ private constructor( provider: SerializerProvider, ) { when { - value.accountLevelRule != null -> generator.writeObject(value.accountLevelRule) + value.unionMember0 != null -> generator.writeObject(value.unionMember0) + value.unionMember1 != null -> generator.writeObject(value.unionMember1) value.cardLevelRule != null -> generator.writeObject(value.cardLevelRule) value.programLevelRule != null -> generator.writeObject(value.programLevelRule) value._json != null -> generator.writeObject(value._json) @@ -443,9 +470,8 @@ private constructor( } } - class AccountLevelRule + class UnionMember0 private constructor( - private val accountTokens: JsonField>, private val name: JsonField, private val state: JsonField, private val additionalProperties: MutableMap, @@ -453,21 +479,9 @@ private constructor( @JsonCreator private constructor( - @JsonProperty("account_tokens") - @ExcludeMissing - accountTokens: JsonField> = JsonMissing.of(), @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), - ) : this(accountTokens, name, state, mutableMapOf()) - - /** - * Account tokens to which the Auth Rule applies. - * - * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun accountTokens(): Optional> = - accountTokens.getOptional("account_tokens") + ) : this(name, state, mutableMapOf()) /** * Auth Rule Name @@ -489,16 +503,6 @@ private constructor( */ fun state(): Optional = state.getOptional("state") - /** - * Returns the raw JSON value of [accountTokens]. - * - * Unlike [accountTokens], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("account_tokens") - @ExcludeMissing - fun _accountTokens(): JsonField> = accountTokens - /** * Returns the raw JSON value of [name]. * @@ -527,51 +531,347 @@ private constructor( companion object { - /** Returns a mutable builder for constructing an instance of [AccountLevelRule]. */ + /** Returns a mutable builder for constructing an instance of [UnionMember0]. */ @JvmStatic fun builder() = Builder() } - /** A builder for [AccountLevelRule]. */ + /** A builder for [UnionMember0]. */ class Builder internal constructor() { - private var accountTokens: JsonField>? = null private var name: JsonField = JsonMissing.of() private var state: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(accountLevelRule: AccountLevelRule) = apply { - accountTokens = accountLevelRule.accountTokens.map { it.toMutableList() } - name = accountLevelRule.name - state = accountLevelRule.state - additionalProperties = accountLevelRule.additionalProperties.toMutableMap() + internal fun from(unionMember0: UnionMember0) = apply { + name = unionMember0.name + state = unionMember0.state + additionalProperties = unionMember0.additionalProperties.toMutableMap() } - /** Account tokens to which the Auth Rule applies. */ - fun accountTokens(accountTokens: List) = - accountTokens(JsonField.of(accountTokens)) + /** Auth Rule Name */ + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** Alias for calling [Builder.name] with `name.orElse(null)`. */ + fun name(name: Optional) = name(name.getOrNull()) /** - * Sets [Builder.accountTokens] to an arbitrary JSON value. + * Sets [Builder.name] to an arbitrary JSON value. * - * You should usually call [Builder.accountTokens] with a well-typed `List` - * value instead. This method is primarily for setting the field to an undocumented - * or not yet supported 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 } + + /** + * The desired state of the Auth Rule. + * + * Note that only deactivating an Auth Rule through this endpoint is supported at + * this time. If you need to (re-)activate an Auth Rule the /promote endpoint should + * be used to promote a draft to the currently active version. + */ + 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 accountTokens(accountTokens: JsonField>) = apply { - this.accountTokens = accountTokens.map { it.toMutableList() } + fun state(state: JsonField) = apply { this.state = state } + + 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) } /** - * Adds a single [String] to [accountTokens]. + * Returns an immutable instance of [UnionMember0]. * - * @throws IllegalStateException if the field was previously set to a non-list. + * Further updates to this [Builder] will not mutate the returned instance. */ - fun addAccountToken(accountToken: String) = apply { - accountTokens = - (accountTokens ?: JsonField.of(mutableListOf())).also { - checkKnown("accountTokens", it).add(accountToken) - } + fun build(): UnionMember0 = + UnionMember0(name, state, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): UnionMember0 = apply { + if (validated) { + return@apply + } + + name() + state().ifPresent { 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 (name.asKnown().isPresent) 1 else 0) + + (state.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The desired state of the Auth Rule. + * + * Note that only deactivating an Auth Rule through this endpoint is supported at this + * time. If you need to (re-)activate an Auth Rule the /promote endpoint should be used + * to promote a draft to the currently active version. + */ + 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 INACTIVE = of("INACTIVE") + + @JvmStatic fun of(value: String) = State(JsonField.of(value)) + } + + /** An enum containing [State]'s known values. */ + enum class Known { + INACTIVE + } + + /** + * 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 { + INACTIVE, + /** + * 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) { + INACTIVE -> Value.INACTIVE + 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) { + INACTIVE -> Known.INACTIVE + 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 UnionMember0 && + name == other.name && + state == other.state && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(name, state, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "UnionMember0{name=$name, state=$state, additionalProperties=$additionalProperties}" + } + + class UnionMember1 + private constructor( + private val name: JsonField, + private val state: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + ) : this(name, state, mutableMapOf()) + + /** + * Auth Rule Name + * + * @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") + + /** + * The desired state of the Auth Rule. + * + * Note that only deactivating an Auth Rule through this endpoint is supported at this + * time. If you need to (re-)activate an Auth Rule the /promote endpoint should be used + * to promote a draft to the currently active version. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun state(): Optional = state.getOptional("state") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + @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 [UnionMember1]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [UnionMember1]. */ + class Builder internal constructor() { + + private var name: JsonField = JsonMissing.of() + private var state: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(unionMember1: UnionMember1) = apply { + name = unionMember1.name + state = unionMember1.state + additionalProperties = unionMember1.additionalProperties.toMutableMap() } /** Auth Rule Name */ @@ -630,27 +930,21 @@ private constructor( } /** - * Returns an immutable instance of [AccountLevelRule]. + * Returns an immutable instance of [UnionMember1]. * * Further updates to this [Builder] will not mutate the returned instance. */ - fun build(): AccountLevelRule = - AccountLevelRule( - (accountTokens ?: JsonMissing.of()).map { it.toImmutable() }, - name, - state, - additionalProperties.toMutableMap(), - ) + fun build(): UnionMember1 = + UnionMember1(name, state, additionalProperties.toMutableMap()) } private var validated: Boolean = false - fun validate(): AccountLevelRule = apply { + fun validate(): UnionMember1 = apply { if (validated) { return@apply } - accountTokens() name() state().ifPresent { it.validate() } validated = true @@ -672,8 +966,7 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (accountTokens.asKnown().getOrNull()?.size ?: 0) + - (if (name.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + (state.asKnown().getOrNull()?.validity() ?: 0) /** @@ -813,21 +1106,18 @@ private constructor( return true } - return other is AccountLevelRule && - accountTokens == other.accountTokens && + return other is UnionMember1 && name == other.name && state == other.state && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { - Objects.hash(accountTokens, name, state, additionalProperties) - } + private val hashCode: Int by lazy { Objects.hash(name, state, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "AccountLevelRule{accountTokens=$accountTokens, name=$name, state=$state, additionalProperties=$additionalProperties}" + "UnionMember1{name=$name, state=$state, additionalProperties=$additionalProperties}" } class CardLevelRule diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthenticationRetrieveResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthenticationRetrieveResponse.kt index 8e4a50d1b..09a5fd32f 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthenticationRetrieveResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/AuthenticationRetrieveResponse.kt @@ -2916,68 +2916,80 @@ private constructor( /** Object containing data about the merchant involved in the e-commerce transaction. */ class Merchant private constructor( + private val riskIndicator: JsonField, private val id: JsonField, private val country: JsonField, private val mcc: JsonField, private val name: JsonField, - private val riskIndicator: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( + @JsonProperty("risk_indicator") + @ExcludeMissing + riskIndicator: JsonField = JsonMissing.of(), @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), @JsonProperty("country") @ExcludeMissing country: JsonField = JsonMissing.of(), @JsonProperty("mcc") @ExcludeMissing mcc: JsonField = JsonMissing.of(), @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), - @JsonProperty("risk_indicator") - @ExcludeMissing - riskIndicator: JsonField = JsonMissing.of(), - ) : this(id, country, mcc, name, riskIndicator, mutableMapOf()) + ) : this(riskIndicator, id, country, mcc, name, mutableMapOf()) /** - * Merchant identifier as assigned by the acquirer. Maps to EMV 3DS field - * `acquirerMerchantId`. + * Object containing additional data indicating additional risk factors related to the + * e-commerce 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 id(): String = id.getRequired("id") + fun riskIndicator(): RiskIndicator = riskIndicator.getRequired("risk_indicator") + + /** + * Merchant identifier as assigned by the acquirer. Maps to EMV 3DS field + * `acquirerMerchantId`. May not be present for non-payment authentications. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") /** * Country code of the merchant requesting 3DS authentication. Maps to EMV 3DS field - * `merchantCountryCode`. Permitted values: ISO 3166-1 alpha-3 country code (e.g., USA). + * `merchantCountryCode`. Permitted values: ISO 3166-1 alpha-3 country code (e.g., USA). May + * not be present for non-payment authentications. * - * @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). + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). */ - fun country(): String = country.getRequired("country") + fun country(): Optional = country.getOptional("country") /** * Merchant category code assigned to the merchant that describes its business activity - * type. Maps to EMV 3DS field `mcc`. + * type. Maps to EMV 3DS field `mcc`. May not be present for non-payment authentications. * - * @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). + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). */ - fun mcc(): String = mcc.getRequired("mcc") + fun mcc(): Optional = mcc.getOptional("mcc") /** - * Name of the merchant. Maps to EMV 3DS field `merchantName`. + * Name of the merchant. Maps to EMV 3DS field `merchantName`. May not be present for + * non-payment authentications. * - * @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). + * @throws LithicInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). */ - fun name(): String = name.getRequired("name") + fun name(): Optional = name.getOptional("name") /** - * Object containing additional data indicating additional risk factors related to the - * e-commerce transaction. + * Returns the raw JSON value of [riskIndicator]. * - * @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). + * Unlike [riskIndicator], this method doesn't throw if the JSON field has an unexpected + * type. */ - fun riskIndicator(): RiskIndicator = riskIndicator.getRequired("risk_indicator") + @JsonProperty("risk_indicator") + @ExcludeMissing + fun _riskIndicator(): JsonField = riskIndicator /** * Returns the raw JSON value of [id]. @@ -3007,16 +3019,6 @@ private constructor( */ @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name - /** - * Returns the raw JSON value of [riskIndicator]. - * - * Unlike [riskIndicator], this method doesn't throw if the JSON field has an unexpected - * type. - */ - @JsonProperty("risk_indicator") - @ExcludeMissing - fun _riskIndicator(): JsonField = riskIndicator - @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -3036,10 +3038,6 @@ private constructor( * * The following fields are required: * ```java - * .id() - * .country() - * .mcc() - * .name() * .riskIndicator() * ``` */ @@ -3049,28 +3047,49 @@ private constructor( /** A builder for [Merchant]. */ class Builder internal constructor() { - private var id: JsonField? = null - private var country: JsonField? = null - private var mcc: JsonField? = null - private var name: JsonField? = null private var riskIndicator: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var country: JsonField = JsonMissing.of() + private var mcc: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(merchant: Merchant) = apply { + riskIndicator = merchant.riskIndicator id = merchant.id country = merchant.country mcc = merchant.mcc name = merchant.name - riskIndicator = merchant.riskIndicator additionalProperties = merchant.additionalProperties.toMutableMap() } + /** + * Object containing additional data indicating additional risk factors related to the + * e-commerce transaction. + */ + fun riskIndicator(riskIndicator: RiskIndicator) = + riskIndicator(JsonField.of(riskIndicator)) + + /** + * Sets [Builder.riskIndicator] to an arbitrary JSON value. + * + * You should usually call [Builder.riskIndicator] with a well-typed [RiskIndicator] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun riskIndicator(riskIndicator: JsonField) = apply { + this.riskIndicator = riskIndicator + } + /** * Merchant identifier as assigned by the acquirer. Maps to EMV 3DS field - * `acquirerMerchantId`. + * `acquirerMerchantId`. May not be present for non-payment authentications. */ - fun id(id: String) = id(JsonField.of(id)) + fun id(id: String?) = id(JsonField.ofNullable(id)) + + /** Alias for calling [Builder.id] with `id.orElse(null)`. */ + fun id(id: Optional) = id(id.getOrNull()) /** * Sets [Builder.id] to an arbitrary JSON value. @@ -3084,8 +3103,12 @@ private constructor( /** * Country code of the merchant requesting 3DS authentication. Maps to EMV 3DS field * `merchantCountryCode`. Permitted values: ISO 3166-1 alpha-3 country code (e.g., USA). + * May not be present for non-payment authentications. */ - fun country(country: String) = country(JsonField.of(country)) + fun country(country: String?) = country(JsonField.ofNullable(country)) + + /** Alias for calling [Builder.country] with `country.orElse(null)`. */ + fun country(country: Optional) = country(country.getOrNull()) /** * Sets [Builder.country] to an arbitrary JSON value. @@ -3098,9 +3121,13 @@ private constructor( /** * Merchant category code assigned to the merchant that describes its business activity - * type. Maps to EMV 3DS field `mcc`. + * type. Maps to EMV 3DS field `mcc`. May not be present for non-payment + * authentications. */ - fun mcc(mcc: String) = mcc(JsonField.of(mcc)) + fun mcc(mcc: String?) = mcc(JsonField.ofNullable(mcc)) + + /** Alias for calling [Builder.mcc] with `mcc.orElse(null)`. */ + fun mcc(mcc: Optional) = mcc(mcc.getOrNull()) /** * Sets [Builder.mcc] to an arbitrary JSON value. @@ -3111,8 +3138,14 @@ private constructor( */ fun mcc(mcc: JsonField) = apply { this.mcc = mcc } - /** Name of the merchant. Maps to EMV 3DS field `merchantName`. */ - fun name(name: String) = name(JsonField.of(name)) + /** + * Name of the merchant. Maps to EMV 3DS field `merchantName`. May not be present for + * non-payment authentications. + */ + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** Alias for calling [Builder.name] with `name.orElse(null)`. */ + fun name(name: Optional) = name(name.getOrNull()) /** * Sets [Builder.name] to an arbitrary JSON value. @@ -3123,24 +3156,6 @@ private constructor( */ fun name(name: JsonField) = apply { this.name = name } - /** - * Object containing additional data indicating additional risk factors related to the - * e-commerce transaction. - */ - fun riskIndicator(riskIndicator: RiskIndicator) = - riskIndicator(JsonField.of(riskIndicator)) - - /** - * Sets [Builder.riskIndicator] to an arbitrary JSON value. - * - * You should usually call [Builder.riskIndicator] with a well-typed [RiskIndicator] - * value instead. This method is primarily for setting the field to an undocumented or - * not yet supported value. - */ - fun riskIndicator(riskIndicator: JsonField) = apply { - this.riskIndicator = riskIndicator - } - fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -3167,10 +3182,6 @@ private constructor( * * The following fields are required: * ```java - * .id() - * .country() - * .mcc() - * .name() * .riskIndicator() * ``` * @@ -3178,11 +3189,11 @@ private constructor( */ fun build(): Merchant = Merchant( - checkRequired("id", id), - checkRequired("country", country), - checkRequired("mcc", mcc), - checkRequired("name", name), checkRequired("riskIndicator", riskIndicator), + id, + country, + mcc, + name, additionalProperties.toMutableMap(), ) } @@ -3194,11 +3205,11 @@ private constructor( return@apply } + riskIndicator().validate() id() country() mcc() name() - riskIndicator().validate() validated = true } @@ -3218,11 +3229,11 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (id.asKnown().isPresent) 1 else 0) + + (riskIndicator.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + (if (country.asKnown().isPresent) 1 else 0) + (if (mcc.asKnown().isPresent) 1 else 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (riskIndicator.asKnown().getOrNull()?.validity() ?: 0) + (if (name.asKnown().isPresent) 1 else 0) /** * Object containing additional data indicating additional risk factors related to the @@ -4491,22 +4502,22 @@ private constructor( } return other is Merchant && + riskIndicator == other.riskIndicator && id == other.id && country == other.country && mcc == other.mcc && name == other.name && - riskIndicator == other.riskIndicator && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(id, country, mcc, name, riskIndicator, additionalProperties) + Objects.hash(riskIndicator, id, country, mcc, name, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Merchant{id=$id, country=$country, mcc=$mcc, name=$name, riskIndicator=$riskIndicator, additionalProperties=$additionalProperties}" + "Merchant{riskIndicator=$riskIndicator, id=$id, country=$country, mcc=$mcc, name=$name, additionalProperties=$additionalProperties}" } /** diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt index 4a4d9b32b..30745976f 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Event.kt @@ -75,6 +75,8 @@ private constructor( * - `card_transaction.updated` - Transaction Lifecycle webhook. See * https://docs.lithic.com/docs/transaction-webhooks. * - `dispute.updated` - A dispute has been updated. + * - `dispute_transaction.created` - A new dispute transaction has been created. + * - `dispute_transaction.updated` - A dispute transaction has been updated. * - `digital_wallet.tokenization_approval_request` - Card network's request to Lithic to * activate a digital wallet token. * - `digital_wallet.tokenization_result` - Notification of the end result of a tokenization, @@ -216,6 +218,8 @@ private constructor( * - `card_transaction.updated` - Transaction Lifecycle webhook. See * https://docs.lithic.com/docs/transaction-webhooks. * - `dispute.updated` - A dispute has been updated. + * - `dispute_transaction.created` - A new dispute transaction has been created. + * - `dispute_transaction.updated` - A dispute transaction has been updated. * - `digital_wallet.tokenization_approval_request` - Card network's request to Lithic to * activate a digital wallet token. * - `digital_wallet.tokenization_result` - Notification of the end result of a @@ -344,6 +348,8 @@ private constructor( * - `card_transaction.updated` - Transaction Lifecycle webhook. See * https://docs.lithic.com/docs/transaction-webhooks. * - `dispute.updated` - A dispute has been updated. + * - `dispute_transaction.created` - A new dispute transaction has been created. + * - `dispute_transaction.updated` - A dispute transaction has been updated. * - `digital_wallet.tokenization_approval_request` - Card network's request to Lithic to * activate a digital wallet token. * - `digital_wallet.tokenization_result` - Notification of the end result of a tokenization, @@ -418,6 +424,10 @@ private constructor( @JvmField val DISPUTE_EVIDENCE_UPLOAD_FAILED = of("dispute_evidence.upload_failed") + @JvmField val DISPUTE_TRANSACTION_CREATED = of("dispute_transaction.created") + + @JvmField val DISPUTE_TRANSACTION_UPDATED = of("dispute_transaction.updated") + @JvmField val EXTERNAL_BANK_ACCOUNT_CREATED = of("external_bank_account.created") @JvmField val EXTERNAL_BANK_ACCOUNT_UPDATED = of("external_bank_account.updated") @@ -498,6 +508,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -555,6 +567,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -618,6 +632,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Value.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Value.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Value.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Value.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Value.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Value.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Value.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Value.EXTERNAL_PAYMENT_CREATED @@ -682,6 +698,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Known.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Known.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Known.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Known.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Known.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Known.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Known.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Known.EXTERNAL_PAYMENT_CREATED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt index 231d1b286..d0f514aab 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventListParams.kt @@ -380,6 +380,10 @@ private constructor( @JvmField val DISPUTE_EVIDENCE_UPLOAD_FAILED = of("dispute_evidence.upload_failed") + @JvmField val DISPUTE_TRANSACTION_CREATED = of("dispute_transaction.created") + + @JvmField val DISPUTE_TRANSACTION_UPDATED = of("dispute_transaction.updated") + @JvmField val EXTERNAL_BANK_ACCOUNT_CREATED = of("external_bank_account.created") @JvmField val EXTERNAL_BANK_ACCOUNT_UPDATED = of("external_bank_account.updated") @@ -460,6 +464,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -517,6 +523,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -580,6 +588,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Value.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Value.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Value.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Value.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Value.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Value.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Value.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Value.EXTERNAL_PAYMENT_CREATED @@ -644,6 +654,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Known.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Known.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Known.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Known.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Known.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Known.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Known.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Known.EXTERNAL_PAYMENT_CREATED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt index 89aa3db79..df632c496 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscription.kt @@ -381,6 +381,10 @@ private constructor( @JvmField val DISPUTE_EVIDENCE_UPLOAD_FAILED = of("dispute_evidence.upload_failed") + @JvmField val DISPUTE_TRANSACTION_CREATED = of("dispute_transaction.created") + + @JvmField val DISPUTE_TRANSACTION_UPDATED = of("dispute_transaction.updated") + @JvmField val EXTERNAL_BANK_ACCOUNT_CREATED = of("external_bank_account.created") @JvmField val EXTERNAL_BANK_ACCOUNT_UPDATED = of("external_bank_account.updated") @@ -461,6 +465,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -518,6 +524,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -581,6 +589,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Value.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Value.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Value.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Value.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Value.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Value.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Value.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Value.EXTERNAL_PAYMENT_CREATED @@ -645,6 +655,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Known.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Known.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Known.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Known.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Known.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Known.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Known.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Known.EXTERNAL_PAYMENT_CREATED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt index 711a4b18d..9acf37a33 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionCreateParams.kt @@ -703,6 +703,10 @@ private constructor( @JvmField val DISPUTE_EVIDENCE_UPLOAD_FAILED = of("dispute_evidence.upload_failed") + @JvmField val DISPUTE_TRANSACTION_CREATED = of("dispute_transaction.created") + + @JvmField val DISPUTE_TRANSACTION_UPDATED = of("dispute_transaction.updated") + @JvmField val EXTERNAL_BANK_ACCOUNT_CREATED = of("external_bank_account.created") @JvmField val EXTERNAL_BANK_ACCOUNT_UPDATED = of("external_bank_account.updated") @@ -783,6 +787,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -840,6 +846,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -903,6 +911,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Value.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Value.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Value.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Value.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Value.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Value.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Value.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Value.EXTERNAL_PAYMENT_CREATED @@ -967,6 +977,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Known.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Known.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Known.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Known.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Known.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Known.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Known.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Known.EXTERNAL_PAYMENT_CREATED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt index 1e7235844..d96bbd4d6 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionSendSimulatedExampleParams.kt @@ -471,6 +471,10 @@ private constructor( @JvmField val DISPUTE_EVIDENCE_UPLOAD_FAILED = of("dispute_evidence.upload_failed") + @JvmField val DISPUTE_TRANSACTION_CREATED = of("dispute_transaction.created") + + @JvmField val DISPUTE_TRANSACTION_UPDATED = of("dispute_transaction.updated") + @JvmField val EXTERNAL_BANK_ACCOUNT_CREATED = of("external_bank_account.created") @JvmField val EXTERNAL_BANK_ACCOUNT_UPDATED = of("external_bank_account.updated") @@ -551,6 +555,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -608,6 +614,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -671,6 +679,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Value.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Value.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Value.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Value.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Value.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Value.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Value.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Value.EXTERNAL_PAYMENT_CREATED @@ -735,6 +745,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Known.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Known.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Known.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Known.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Known.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Known.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Known.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Known.EXTERNAL_PAYMENT_CREATED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt index e11b7d2d5..42852f27c 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/EventSubscriptionUpdateParams.kt @@ -726,6 +726,10 @@ private constructor( @JvmField val DISPUTE_EVIDENCE_UPLOAD_FAILED = of("dispute_evidence.upload_failed") + @JvmField val DISPUTE_TRANSACTION_CREATED = of("dispute_transaction.created") + + @JvmField val DISPUTE_TRANSACTION_UPDATED = of("dispute_transaction.updated") + @JvmField val EXTERNAL_BANK_ACCOUNT_CREATED = of("external_bank_account.created") @JvmField val EXTERNAL_BANK_ACCOUNT_UPDATED = of("external_bank_account.updated") @@ -806,6 +810,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -863,6 +869,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED, DISPUTE_UPDATED, DISPUTE_EVIDENCE_UPLOAD_FAILED, + DISPUTE_TRANSACTION_CREATED, + DISPUTE_TRANSACTION_UPDATED, EXTERNAL_BANK_ACCOUNT_CREATED, EXTERNAL_BANK_ACCOUNT_UPDATED, EXTERNAL_PAYMENT_CREATED, @@ -926,6 +934,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Value.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Value.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Value.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Value.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Value.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Value.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Value.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Value.EXTERNAL_PAYMENT_CREATED @@ -990,6 +1000,8 @@ private constructor( DIGITAL_WALLET_TOKENIZATION_UPDATED -> Known.DIGITAL_WALLET_TOKENIZATION_UPDATED DISPUTE_UPDATED -> Known.DISPUTE_UPDATED DISPUTE_EVIDENCE_UPLOAD_FAILED -> Known.DISPUTE_EVIDENCE_UPLOAD_FAILED + DISPUTE_TRANSACTION_CREATED -> Known.DISPUTE_TRANSACTION_CREATED + DISPUTE_TRANSACTION_UPDATED -> Known.DISPUTE_TRANSACTION_UPDATED EXTERNAL_BANK_ACCOUNT_CREATED -> Known.EXTERNAL_BANK_ACCOUNT_CREATED EXTERNAL_BANK_ACCOUNT_UPDATED -> Known.EXTERNAL_BANK_ACCOUNT_UPDATED EXTERNAL_PAYMENT_CREATED -> Known.EXTERNAL_PAYMENT_CREATED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt index 735e2b39a..84cd8285e 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/Transaction.kt @@ -7034,6 +7034,8 @@ private constructor( companion object { + @JvmField val ACCOUNT_PAUSED = of("ACCOUNT_PAUSED") + @JvmField val ACCOUNT_STATE_TRANSACTION_FAIL = of("ACCOUNT_STATE_TRANSACTION_FAIL") @JvmField val APPROVED = of("APPROVED") @@ -7085,6 +7087,7 @@ private constructor( /** An enum containing [DeclineResult]'s known values. */ enum class Known { + ACCOUNT_PAUSED, ACCOUNT_STATE_TRANSACTION_FAIL, APPROVED, BANK_CONNECTION_ERROR, @@ -7120,6 +7123,7 @@ private constructor( * - It was constructed with an arbitrary value using the [of] method. */ enum class Value { + ACCOUNT_PAUSED, ACCOUNT_STATE_TRANSACTION_FAIL, APPROVED, BANK_CONNECTION_ERROR, @@ -7159,6 +7163,7 @@ private constructor( */ fun value(): Value = when (this) { + ACCOUNT_PAUSED -> Value.ACCOUNT_PAUSED ACCOUNT_STATE_TRANSACTION_FAIL -> Value.ACCOUNT_STATE_TRANSACTION_FAIL APPROVED -> Value.APPROVED BANK_CONNECTION_ERROR -> Value.BANK_CONNECTION_ERROR @@ -7196,6 +7201,7 @@ private constructor( */ fun known(): Known = when (this) { + ACCOUNT_PAUSED -> Known.ACCOUNT_PAUSED ACCOUNT_STATE_TRANSACTION_FAIL -> Known.ACCOUNT_STATE_TRANSACTION_FAIL APPROVED -> Known.APPROVED BANK_CONNECTION_ERROR -> Known.BANK_CONNECTION_ERROR @@ -9415,6 +9421,8 @@ private constructor( val ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED = of("ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED") + @JvmField val ACCOUNT_PAUSED = of("ACCOUNT_PAUSED") + @JvmField val ACCOUNT_UNDER_REVIEW = of("ACCOUNT_UNDER_REVIEW") @JvmField val ADDRESS_INCORRECT = of("ADDRESS_INCORRECT") @@ -9529,6 +9537,7 @@ private constructor( ACCOUNT_INACTIVE, ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED, ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED, + ACCOUNT_PAUSED, ACCOUNT_UNDER_REVIEW, ADDRESS_INCORRECT, APPROVED, @@ -9593,6 +9602,7 @@ private constructor( ACCOUNT_INACTIVE, ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED, ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED, + ACCOUNT_PAUSED, ACCOUNT_UNDER_REVIEW, ADDRESS_INCORRECT, APPROVED, @@ -9663,6 +9673,7 @@ private constructor( Value.ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED -> Value.ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED + ACCOUNT_PAUSED -> Value.ACCOUNT_PAUSED ACCOUNT_UNDER_REVIEW -> Value.ACCOUNT_UNDER_REVIEW ADDRESS_INCORRECT -> Value.ADDRESS_INCORRECT APPROVED -> Value.APPROVED @@ -9734,6 +9745,7 @@ private constructor( Known.ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED -> Known.ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED + ACCOUNT_PAUSED -> Known.ACCOUNT_PAUSED ACCOUNT_UNDER_REVIEW -> Known.ACCOUNT_UNDER_REVIEW ADDRESS_INCORRECT -> Known.ADDRESS_INCORRECT APPROVED -> Known.APPROVED @@ -11430,6 +11442,8 @@ private constructor( companion object { + @JvmField val ACCOUNT_PAUSED = of("ACCOUNT_PAUSED") + @JvmField val ACCOUNT_STATE_TRANSACTION_FAIL = of("ACCOUNT_STATE_TRANSACTION_FAIL") @JvmField val APPROVED = of("APPROVED") @@ -11481,6 +11495,7 @@ private constructor( /** An enum containing [DeclineResult]'s known values. */ enum class Known { + ACCOUNT_PAUSED, ACCOUNT_STATE_TRANSACTION_FAIL, APPROVED, BANK_CONNECTION_ERROR, @@ -11516,6 +11531,7 @@ private constructor( * - It was constructed with an arbitrary value using the [of] method. */ enum class Value { + ACCOUNT_PAUSED, ACCOUNT_STATE_TRANSACTION_FAIL, APPROVED, BANK_CONNECTION_ERROR, @@ -11555,6 +11571,7 @@ private constructor( */ fun value(): Value = when (this) { + ACCOUNT_PAUSED -> Value.ACCOUNT_PAUSED ACCOUNT_STATE_TRANSACTION_FAIL -> Value.ACCOUNT_STATE_TRANSACTION_FAIL APPROVED -> Value.APPROVED BANK_CONNECTION_ERROR -> Value.BANK_CONNECTION_ERROR @@ -11592,6 +11609,7 @@ private constructor( */ fun known(): Known = when (this) { + ACCOUNT_PAUSED -> Known.ACCOUNT_PAUSED ACCOUNT_STATE_TRANSACTION_FAIL -> Known.ACCOUNT_STATE_TRANSACTION_FAIL APPROVED -> Known.APPROVED BANK_CONNECTION_ERROR -> Known.BANK_CONNECTION_ERROR @@ -11998,6 +12016,8 @@ private constructor( val ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED = of("ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED") + @JvmField val ACCOUNT_PAUSED = of("ACCOUNT_PAUSED") + @JvmField val ACCOUNT_UNDER_REVIEW = of("ACCOUNT_UNDER_REVIEW") @JvmField val ADDRESS_INCORRECT = of("ADDRESS_INCORRECT") @@ -12114,6 +12134,7 @@ private constructor( ACCOUNT_INACTIVE, ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED, ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED, + ACCOUNT_PAUSED, ACCOUNT_UNDER_REVIEW, ADDRESS_INCORRECT, APPROVED, @@ -12180,6 +12201,7 @@ private constructor( ACCOUNT_INACTIVE, ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED, ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED, + ACCOUNT_PAUSED, ACCOUNT_UNDER_REVIEW, ADDRESS_INCORRECT, APPROVED, @@ -12251,6 +12273,7 @@ private constructor( Value.ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED -> Value.ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED + ACCOUNT_PAUSED -> Value.ACCOUNT_PAUSED ACCOUNT_UNDER_REVIEW -> Value.ACCOUNT_UNDER_REVIEW ADDRESS_INCORRECT -> Value.ADDRESS_INCORRECT APPROVED -> Value.APPROVED @@ -12325,6 +12348,7 @@ private constructor( Known.ACCOUNT_LIFETIME_SPEND_LIMIT_EXCEEDED ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED -> Known.ACCOUNT_MONTHLY_SPEND_LIMIT_EXCEEDED + ACCOUNT_PAUSED -> Known.ACCOUNT_PAUSED ACCOUNT_UNDER_REVIEW -> Known.ACCOUNT_UNDER_REVIEW ADDRESS_INCORRECT -> Known.ADDRESS_INCORRECT APPROVED -> Known.APPROVED diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ApplyResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ApplyResponse.kt index 7335e810c..7cba5f0ad 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ApplyResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ApplyResponse.kt @@ -35,6 +35,7 @@ class V2ApplyResponse private constructor( private val token: JsonField, private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val cardTokens: JsonField>, private val currentVersion: JsonField, private val draftVersion: JsonField, @@ -53,6 +54,9 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), @@ -77,6 +81,7 @@ private constructor( ) : this( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -105,6 +110,15 @@ private constructor( */ fun accountTokens(): List = accountTokens.getRequired("account_tokens") + /** + * Business Account tokens to which the Auth Rule applies. + * + * @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 businessAccountTokens(): List = + businessAccountTokens.getRequired("business_account_tokens") + /** * Card tokens to which the Auth Rule applies. * @@ -126,7 +140,7 @@ private constructor( fun draftVersion(): Optional = draftVersion.getOptional("draft_version") /** - * The type of event stream the Auth rule applies to. + * The event stream during which the rule will be evaluated. * * @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). @@ -158,12 +172,13 @@ private constructor( fun state(): AuthRuleState = state.getRequired("state") /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION 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). @@ -195,6 +210,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + /** * Returns the raw JSON value of [cardTokens]. * @@ -292,6 +317,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -310,6 +336,7 @@ private constructor( private var token: JsonField? = null private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var cardTokens: JsonField>? = null private var currentVersion: JsonField? = null private var draftVersion: JsonField? = null @@ -325,6 +352,7 @@ private constructor( internal fun from(v2ApplyResponse: V2ApplyResponse) = apply { token = v2ApplyResponse.token accountTokens = v2ApplyResponse.accountTokens.map { it.toMutableList() } + businessAccountTokens = v2ApplyResponse.businessAccountTokens.map { it.toMutableList() } cardTokens = v2ApplyResponse.cardTokens.map { it.toMutableList() } currentVersion = v2ApplyResponse.currentVersion draftVersion = v2ApplyResponse.draftVersion @@ -374,6 +402,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + /** Card tokens to which the Auth Rule applies. */ fun cardTokens(cardTokens: List) = cardTokens(JsonField.of(cardTokens)) @@ -436,7 +491,7 @@ private constructor( this.draftVersion = draftVersion } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) /** @@ -491,12 +546,13 @@ private constructor( fun state(state: JsonField) = apply { this.state = state } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event + * streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -564,6 +620,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -580,6 +637,9 @@ private constructor( V2ApplyResponse( checkRequired("token", token), checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + checkRequired("businessAccountTokens", businessAccountTokens).map { + it.toImmutable() + }, checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, checkRequired("currentVersion", currentVersion), checkRequired("draftVersion", draftVersion), @@ -602,6 +662,7 @@ private constructor( token() accountTokens() + businessAccountTokens() cardTokens() currentVersion().ifPresent { it.validate() } draftVersion().ifPresent { it.validate() } @@ -631,6 +692,7 @@ private constructor( internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + (cardTokens.asKnown().getOrNull()?.size ?: 0) + (currentVersion.asKnown().getOrNull()?.validity() ?: 0) + (draftVersion.asKnown().getOrNull()?.validity() ?: 0) + @@ -767,6 +829,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -861,6 +934,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -875,6 +950,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -883,6 +962,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -894,6 +975,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -904,6 +988,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -937,6 +1023,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -975,6 +1067,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -988,7 +1084,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -997,6 +1094,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1007,6 +1105,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1028,6 +1128,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1046,6 +1151,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1080,6 +1189,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1112,11 +1231,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1266,6 +2810,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1360,6 +2915,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -1374,6 +2931,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1382,6 +2943,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1393,6 +2956,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1403,6 +2969,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -1436,6 +3004,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1474,6 +3048,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1487,7 +3065,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1496,6 +3075,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1506,6 +3086,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1527,6 +3109,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1545,6 +3132,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1579,6 +3170,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1611,11 +3212,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1639,7 +4665,7 @@ private constructor( "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ class EventStream @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1899,12 +4925,13 @@ private constructor( } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1927,7 +4954,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1937,7 +4964,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1953,7 +4980,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -1972,7 +4999,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1990,7 +5017,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2054,6 +5081,7 @@ private constructor( return other is V2ApplyResponse && token == other.token && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && cardTokens == other.cardTokens && currentVersion == other.currentVersion && draftVersion == other.draftVersion && @@ -2070,6 +5098,7 @@ private constructor( Objects.hash( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -2086,5 +5115,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "V2ApplyResponse{token=$token, accountTokens=$accountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" + "V2ApplyResponse{token=$token, accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2CreateResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2CreateResponse.kt index 0f061dc24..2f94cea9f 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2CreateResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2CreateResponse.kt @@ -35,6 +35,7 @@ class V2CreateResponse private constructor( private val token: JsonField, private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val cardTokens: JsonField>, private val currentVersion: JsonField, private val draftVersion: JsonField, @@ -53,6 +54,9 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), @@ -77,6 +81,7 @@ private constructor( ) : this( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -105,6 +110,15 @@ private constructor( */ fun accountTokens(): List = accountTokens.getRequired("account_tokens") + /** + * Business Account tokens to which the Auth Rule applies. + * + * @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 businessAccountTokens(): List = + businessAccountTokens.getRequired("business_account_tokens") + /** * Card tokens to which the Auth Rule applies. * @@ -126,7 +140,7 @@ private constructor( fun draftVersion(): Optional = draftVersion.getOptional("draft_version") /** - * The type of event stream the Auth rule applies to. + * The event stream during which the rule will be evaluated. * * @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). @@ -158,12 +172,13 @@ private constructor( fun state(): AuthRuleState = state.getRequired("state") /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION 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). @@ -195,6 +210,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + /** * Returns the raw JSON value of [cardTokens]. * @@ -292,6 +317,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -310,6 +336,7 @@ private constructor( private var token: JsonField? = null private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var cardTokens: JsonField>? = null private var currentVersion: JsonField? = null private var draftVersion: JsonField? = null @@ -325,6 +352,8 @@ private constructor( internal fun from(v2CreateResponse: V2CreateResponse) = apply { token = v2CreateResponse.token accountTokens = v2CreateResponse.accountTokens.map { it.toMutableList() } + businessAccountTokens = + v2CreateResponse.businessAccountTokens.map { it.toMutableList() } cardTokens = v2CreateResponse.cardTokens.map { it.toMutableList() } currentVersion = v2CreateResponse.currentVersion draftVersion = v2CreateResponse.draftVersion @@ -374,6 +403,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + /** Card tokens to which the Auth Rule applies. */ fun cardTokens(cardTokens: List) = cardTokens(JsonField.of(cardTokens)) @@ -436,7 +492,7 @@ private constructor( this.draftVersion = draftVersion } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) /** @@ -491,12 +547,13 @@ private constructor( fun state(state: JsonField) = apply { this.state = state } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event + * streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -564,6 +621,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -580,6 +638,9 @@ private constructor( V2CreateResponse( checkRequired("token", token), checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + checkRequired("businessAccountTokens", businessAccountTokens).map { + it.toImmutable() + }, checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, checkRequired("currentVersion", currentVersion), checkRequired("draftVersion", draftVersion), @@ -602,6 +663,7 @@ private constructor( token() accountTokens() + businessAccountTokens() cardTokens() currentVersion().ifPresent { it.validate() } draftVersion().ifPresent { it.validate() } @@ -631,6 +693,7 @@ private constructor( internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + (cardTokens.asKnown().getOrNull()?.size ?: 0) + (currentVersion.asKnown().getOrNull()?.validity() ?: 0) + (draftVersion.asKnown().getOrNull()?.validity() ?: 0) + @@ -767,6 +830,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -861,6 +935,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -875,6 +951,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -883,6 +963,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -894,6 +976,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -904,6 +989,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -937,6 +1024,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -975,6 +1068,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -988,7 +1085,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -997,6 +1095,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1007,6 +1106,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1028,6 +1129,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1046,6 +1152,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1080,6 +1190,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1112,11 +1232,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1266,6 +2811,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1360,6 +2916,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -1374,6 +2932,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1382,6 +2944,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1393,6 +2957,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1403,6 +2970,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -1436,6 +3005,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1474,6 +3049,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1487,7 +3066,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1496,6 +3076,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1506,6 +3087,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1527,6 +3110,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1545,6 +3133,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1579,6 +3171,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1611,11 +3213,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1639,7 +4666,7 @@ private constructor( "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ class EventStream @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1899,12 +4926,13 @@ private constructor( } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1927,7 +4955,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1937,7 +4965,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1953,7 +4981,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -1972,7 +5000,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1990,7 +5018,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2054,6 +5082,7 @@ private constructor( return other is V2CreateResponse && token == other.token && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && cardTokens == other.cardTokens && currentVersion == other.currentVersion && draftVersion == other.draftVersion && @@ -2070,6 +5099,7 @@ private constructor( Objects.hash( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -2086,5 +5116,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "V2CreateResponse{token=$token, accountTokens=$accountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" + "V2CreateResponse{token=$token, accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2DraftResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2DraftResponse.kt index b091735dd..834dc6a5c 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2DraftResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2DraftResponse.kt @@ -35,6 +35,7 @@ class V2DraftResponse private constructor( private val token: JsonField, private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val cardTokens: JsonField>, private val currentVersion: JsonField, private val draftVersion: JsonField, @@ -53,6 +54,9 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), @@ -77,6 +81,7 @@ private constructor( ) : this( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -105,6 +110,15 @@ private constructor( */ fun accountTokens(): List = accountTokens.getRequired("account_tokens") + /** + * Business Account tokens to which the Auth Rule applies. + * + * @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 businessAccountTokens(): List = + businessAccountTokens.getRequired("business_account_tokens") + /** * Card tokens to which the Auth Rule applies. * @@ -126,7 +140,7 @@ private constructor( fun draftVersion(): Optional = draftVersion.getOptional("draft_version") /** - * The type of event stream the Auth rule applies to. + * The event stream during which the rule will be evaluated. * * @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). @@ -158,12 +172,13 @@ private constructor( fun state(): AuthRuleState = state.getRequired("state") /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION 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). @@ -195,6 +210,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + /** * Returns the raw JSON value of [cardTokens]. * @@ -292,6 +317,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -310,6 +336,7 @@ private constructor( private var token: JsonField? = null private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var cardTokens: JsonField>? = null private var currentVersion: JsonField? = null private var draftVersion: JsonField? = null @@ -325,6 +352,7 @@ private constructor( internal fun from(v2DraftResponse: V2DraftResponse) = apply { token = v2DraftResponse.token accountTokens = v2DraftResponse.accountTokens.map { it.toMutableList() } + businessAccountTokens = v2DraftResponse.businessAccountTokens.map { it.toMutableList() } cardTokens = v2DraftResponse.cardTokens.map { it.toMutableList() } currentVersion = v2DraftResponse.currentVersion draftVersion = v2DraftResponse.draftVersion @@ -374,6 +402,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + /** Card tokens to which the Auth Rule applies. */ fun cardTokens(cardTokens: List) = cardTokens(JsonField.of(cardTokens)) @@ -436,7 +491,7 @@ private constructor( this.draftVersion = draftVersion } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) /** @@ -491,12 +546,13 @@ private constructor( fun state(state: JsonField) = apply { this.state = state } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event + * streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -564,6 +620,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -580,6 +637,9 @@ private constructor( V2DraftResponse( checkRequired("token", token), checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + checkRequired("businessAccountTokens", businessAccountTokens).map { + it.toImmutable() + }, checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, checkRequired("currentVersion", currentVersion), checkRequired("draftVersion", draftVersion), @@ -602,6 +662,7 @@ private constructor( token() accountTokens() + businessAccountTokens() cardTokens() currentVersion().ifPresent { it.validate() } draftVersion().ifPresent { it.validate() } @@ -631,6 +692,7 @@ private constructor( internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + (cardTokens.asKnown().getOrNull()?.size ?: 0) + (currentVersion.asKnown().getOrNull()?.validity() ?: 0) + (draftVersion.asKnown().getOrNull()?.validity() ?: 0) + @@ -767,6 +829,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -861,6 +934,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -875,6 +950,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -883,6 +962,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -894,6 +975,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -904,6 +988,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -937,6 +1023,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -975,6 +1067,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -988,7 +1084,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -997,6 +1094,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1007,6 +1105,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1028,6 +1128,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1046,6 +1151,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1080,6 +1189,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1112,11 +1231,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1266,6 +2810,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1360,6 +2915,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -1374,6 +2931,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1382,6 +2943,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1393,6 +2956,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1403,6 +2969,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -1436,6 +3004,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1474,6 +3048,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1487,7 +3065,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1496,6 +3075,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1506,6 +3086,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1527,6 +3109,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1545,6 +3132,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1579,6 +3170,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1611,11 +3212,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1639,7 +4665,7 @@ private constructor( "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ class EventStream @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1899,12 +4925,13 @@ private constructor( } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1927,7 +4954,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1937,7 +4964,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1953,7 +4980,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -1972,7 +4999,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1990,7 +5017,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2054,6 +5081,7 @@ private constructor( return other is V2DraftResponse && token == other.token && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && cardTokens == other.cardTokens && currentVersion == other.currentVersion && draftVersion == other.draftVersion && @@ -2070,6 +5098,7 @@ private constructor( Objects.hash( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -2086,5 +5115,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "V2DraftResponse{token=$token, accountTokens=$accountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" + "V2DraftResponse{token=$token, accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResponse.kt index 0aacbf220..7db8614d7 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2ListResponse.kt @@ -35,6 +35,7 @@ class V2ListResponse private constructor( private val token: JsonField, private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val cardTokens: JsonField>, private val currentVersion: JsonField, private val draftVersion: JsonField, @@ -53,6 +54,9 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), @@ -77,6 +81,7 @@ private constructor( ) : this( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -105,6 +110,15 @@ private constructor( */ fun accountTokens(): List = accountTokens.getRequired("account_tokens") + /** + * Business Account tokens to which the Auth Rule applies. + * + * @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 businessAccountTokens(): List = + businessAccountTokens.getRequired("business_account_tokens") + /** * Card tokens to which the Auth Rule applies. * @@ -126,7 +140,7 @@ private constructor( fun draftVersion(): Optional = draftVersion.getOptional("draft_version") /** - * The type of event stream the Auth rule applies to. + * The event stream during which the rule will be evaluated. * * @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). @@ -158,12 +172,13 @@ private constructor( fun state(): AuthRuleState = state.getRequired("state") /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION 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). @@ -195,6 +210,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + /** * Returns the raw JSON value of [cardTokens]. * @@ -292,6 +317,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -310,6 +336,7 @@ private constructor( private var token: JsonField? = null private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var cardTokens: JsonField>? = null private var currentVersion: JsonField? = null private var draftVersion: JsonField? = null @@ -325,6 +352,7 @@ private constructor( internal fun from(v2ListResponse: V2ListResponse) = apply { token = v2ListResponse.token accountTokens = v2ListResponse.accountTokens.map { it.toMutableList() } + businessAccountTokens = v2ListResponse.businessAccountTokens.map { it.toMutableList() } cardTokens = v2ListResponse.cardTokens.map { it.toMutableList() } currentVersion = v2ListResponse.currentVersion draftVersion = v2ListResponse.draftVersion @@ -374,6 +402,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + /** Card tokens to which the Auth Rule applies. */ fun cardTokens(cardTokens: List) = cardTokens(JsonField.of(cardTokens)) @@ -436,7 +491,7 @@ private constructor( this.draftVersion = draftVersion } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) /** @@ -491,12 +546,13 @@ private constructor( fun state(state: JsonField) = apply { this.state = state } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event + * streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -564,6 +620,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -580,6 +637,9 @@ private constructor( V2ListResponse( checkRequired("token", token), checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + checkRequired("businessAccountTokens", businessAccountTokens).map { + it.toImmutable() + }, checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, checkRequired("currentVersion", currentVersion), checkRequired("draftVersion", draftVersion), @@ -602,6 +662,7 @@ private constructor( token() accountTokens() + businessAccountTokens() cardTokens() currentVersion().ifPresent { it.validate() } draftVersion().ifPresent { it.validate() } @@ -631,6 +692,7 @@ private constructor( internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + (cardTokens.asKnown().getOrNull()?.size ?: 0) + (currentVersion.asKnown().getOrNull()?.validity() ?: 0) + (draftVersion.asKnown().getOrNull()?.validity() ?: 0) + @@ -767,6 +829,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -861,6 +934,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -875,6 +950,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -883,6 +962,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -894,6 +975,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -904,6 +988,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -937,6 +1023,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -975,6 +1067,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -988,7 +1084,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -997,6 +1094,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1007,6 +1105,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1028,6 +1128,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1046,6 +1151,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1080,6 +1189,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1112,11 +1231,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1266,6 +2810,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1360,6 +2915,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -1374,6 +2931,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1382,6 +2943,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1393,6 +2956,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1403,6 +2969,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -1436,6 +3004,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1474,6 +3048,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1487,7 +3065,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1496,6 +3075,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1506,6 +3086,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1527,6 +3109,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1545,6 +3132,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1579,6 +3170,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1611,11 +3212,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1639,7 +4665,7 @@ private constructor( "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ class EventStream @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1899,12 +4925,13 @@ private constructor( } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1927,7 +4954,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1937,7 +4964,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1953,7 +4980,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -1972,7 +4999,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1990,7 +5017,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2054,6 +5081,7 @@ private constructor( return other is V2ListResponse && token == other.token && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && cardTokens == other.cardTokens && currentVersion == other.currentVersion && draftVersion == other.draftVersion && @@ -2070,6 +5098,7 @@ private constructor( Objects.hash( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -2086,5 +5115,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "V2ListResponse{token=$token, accountTokens=$accountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" + "V2ListResponse{token=$token, accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2PromoteResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2PromoteResponse.kt index fd3870d28..8d570d30f 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2PromoteResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2PromoteResponse.kt @@ -35,6 +35,7 @@ class V2PromoteResponse private constructor( private val token: JsonField, private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val cardTokens: JsonField>, private val currentVersion: JsonField, private val draftVersion: JsonField, @@ -53,6 +54,9 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), @@ -77,6 +81,7 @@ private constructor( ) : this( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -105,6 +110,15 @@ private constructor( */ fun accountTokens(): List = accountTokens.getRequired("account_tokens") + /** + * Business Account tokens to which the Auth Rule applies. + * + * @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 businessAccountTokens(): List = + businessAccountTokens.getRequired("business_account_tokens") + /** * Card tokens to which the Auth Rule applies. * @@ -126,7 +140,7 @@ private constructor( fun draftVersion(): Optional = draftVersion.getOptional("draft_version") /** - * The type of event stream the Auth rule applies to. + * The event stream during which the rule will be evaluated. * * @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). @@ -158,12 +172,13 @@ private constructor( fun state(): AuthRuleState = state.getRequired("state") /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION 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). @@ -195,6 +210,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + /** * Returns the raw JSON value of [cardTokens]. * @@ -292,6 +317,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -310,6 +336,7 @@ private constructor( private var token: JsonField? = null private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var cardTokens: JsonField>? = null private var currentVersion: JsonField? = null private var draftVersion: JsonField? = null @@ -325,6 +352,8 @@ private constructor( internal fun from(v2PromoteResponse: V2PromoteResponse) = apply { token = v2PromoteResponse.token accountTokens = v2PromoteResponse.accountTokens.map { it.toMutableList() } + businessAccountTokens = + v2PromoteResponse.businessAccountTokens.map { it.toMutableList() } cardTokens = v2PromoteResponse.cardTokens.map { it.toMutableList() } currentVersion = v2PromoteResponse.currentVersion draftVersion = v2PromoteResponse.draftVersion @@ -374,6 +403,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + /** Card tokens to which the Auth Rule applies. */ fun cardTokens(cardTokens: List) = cardTokens(JsonField.of(cardTokens)) @@ -436,7 +492,7 @@ private constructor( this.draftVersion = draftVersion } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) /** @@ -491,12 +547,13 @@ private constructor( fun state(state: JsonField) = apply { this.state = state } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event + * streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -564,6 +621,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -580,6 +638,9 @@ private constructor( V2PromoteResponse( checkRequired("token", token), checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + checkRequired("businessAccountTokens", businessAccountTokens).map { + it.toImmutable() + }, checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, checkRequired("currentVersion", currentVersion), checkRequired("draftVersion", draftVersion), @@ -602,6 +663,7 @@ private constructor( token() accountTokens() + businessAccountTokens() cardTokens() currentVersion().ifPresent { it.validate() } draftVersion().ifPresent { it.validate() } @@ -631,6 +693,7 @@ private constructor( internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + (cardTokens.asKnown().getOrNull()?.size ?: 0) + (currentVersion.asKnown().getOrNull()?.validity() ?: 0) + (draftVersion.asKnown().getOrNull()?.validity() ?: 0) + @@ -767,6 +830,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -861,6 +935,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -875,6 +951,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -883,6 +963,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -894,6 +976,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -904,6 +989,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -937,6 +1024,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -975,6 +1068,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -988,7 +1085,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -997,6 +1095,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1007,6 +1106,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1028,6 +1129,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1046,6 +1152,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1080,6 +1190,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1112,11 +1232,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1266,6 +2811,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1360,6 +2916,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -1374,6 +2932,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1382,6 +2944,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1393,6 +2957,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1403,6 +2970,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -1436,6 +3005,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1474,6 +3049,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1487,7 +3066,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1496,6 +3076,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1506,6 +3087,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1527,6 +3110,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1545,6 +3133,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1579,6 +3171,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1611,11 +3213,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1639,7 +4666,7 @@ private constructor( "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ class EventStream @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1899,12 +4926,13 @@ private constructor( } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1927,7 +4955,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1937,7 +4965,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1953,7 +4981,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -1972,7 +5000,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1990,7 +5018,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2054,6 +5082,7 @@ private constructor( return other is V2PromoteResponse && token == other.token && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && cardTokens == other.cardTokens && currentVersion == other.currentVersion && draftVersion == other.draftVersion && @@ -2070,6 +5099,7 @@ private constructor( Objects.hash( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -2086,5 +5116,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "V2PromoteResponse{token=$token, accountTokens=$accountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" + "V2PromoteResponse{token=$token, accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveResponse.kt index 054ab7270..516ccc604 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2RetrieveResponse.kt @@ -35,6 +35,7 @@ class V2RetrieveResponse private constructor( private val token: JsonField, private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val cardTokens: JsonField>, private val currentVersion: JsonField, private val draftVersion: JsonField, @@ -53,6 +54,9 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), @@ -77,6 +81,7 @@ private constructor( ) : this( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -105,6 +110,15 @@ private constructor( */ fun accountTokens(): List = accountTokens.getRequired("account_tokens") + /** + * Business Account tokens to which the Auth Rule applies. + * + * @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 businessAccountTokens(): List = + businessAccountTokens.getRequired("business_account_tokens") + /** * Card tokens to which the Auth Rule applies. * @@ -126,7 +140,7 @@ private constructor( fun draftVersion(): Optional = draftVersion.getOptional("draft_version") /** - * The type of event stream the Auth rule applies to. + * The event stream during which the rule will be evaluated. * * @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). @@ -158,12 +172,13 @@ private constructor( fun state(): AuthRuleState = state.getRequired("state") /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION 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). @@ -195,6 +210,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + /** * Returns the raw JSON value of [cardTokens]. * @@ -292,6 +317,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -310,6 +336,7 @@ private constructor( private var token: JsonField? = null private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var cardTokens: JsonField>? = null private var currentVersion: JsonField? = null private var draftVersion: JsonField? = null @@ -325,6 +352,8 @@ private constructor( internal fun from(v2RetrieveResponse: V2RetrieveResponse) = apply { token = v2RetrieveResponse.token accountTokens = v2RetrieveResponse.accountTokens.map { it.toMutableList() } + businessAccountTokens = + v2RetrieveResponse.businessAccountTokens.map { it.toMutableList() } cardTokens = v2RetrieveResponse.cardTokens.map { it.toMutableList() } currentVersion = v2RetrieveResponse.currentVersion draftVersion = v2RetrieveResponse.draftVersion @@ -374,6 +403,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + /** Card tokens to which the Auth Rule applies. */ fun cardTokens(cardTokens: List) = cardTokens(JsonField.of(cardTokens)) @@ -436,7 +492,7 @@ private constructor( this.draftVersion = draftVersion } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) /** @@ -491,12 +547,13 @@ private constructor( fun state(state: JsonField) = apply { this.state = state } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event + * streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -564,6 +621,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -580,6 +638,9 @@ private constructor( V2RetrieveResponse( checkRequired("token", token), checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + checkRequired("businessAccountTokens", businessAccountTokens).map { + it.toImmutable() + }, checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, checkRequired("currentVersion", currentVersion), checkRequired("draftVersion", draftVersion), @@ -602,6 +663,7 @@ private constructor( token() accountTokens() + businessAccountTokens() cardTokens() currentVersion().ifPresent { it.validate() } draftVersion().ifPresent { it.validate() } @@ -631,6 +693,7 @@ private constructor( internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + (cardTokens.asKnown().getOrNull()?.size ?: 0) + (currentVersion.asKnown().getOrNull()?.validity() ?: 0) + (draftVersion.asKnown().getOrNull()?.validity() ?: 0) + @@ -767,6 +830,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -861,6 +935,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -875,6 +951,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -883,6 +963,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -894,6 +976,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -904,6 +989,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -937,6 +1024,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -975,6 +1068,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -988,7 +1085,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -997,6 +1095,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1007,6 +1106,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1028,6 +1129,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1046,6 +1152,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1080,6 +1190,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1112,11 +1232,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1266,6 +2811,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1360,6 +2916,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -1374,6 +2932,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1382,6 +2944,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1393,6 +2957,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1403,6 +2970,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -1436,6 +3005,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1474,6 +3049,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1487,7 +3066,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1496,6 +3076,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1506,6 +3087,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1527,6 +3110,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1545,6 +3133,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1579,6 +3171,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1611,11 +3213,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1639,7 +4666,7 @@ private constructor( "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ class EventStream @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1899,12 +4926,13 @@ private constructor( } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1927,7 +4955,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1937,7 +4965,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1953,7 +4981,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -1972,7 +5000,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1990,7 +5018,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2054,6 +5082,7 @@ private constructor( return other is V2RetrieveResponse && token == other.token && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && cardTokens == other.cardTokens && currentVersion == other.currentVersion && draftVersion == other.draftVersion && @@ -2070,6 +5099,7 @@ private constructor( Objects.hash( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -2086,5 +5116,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "V2RetrieveResponse{token=$token, accountTokens=$accountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" + "V2RetrieveResponse{token=$token, accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2UpdateResponse.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2UpdateResponse.kt index 601e37916..c17a400d8 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2UpdateResponse.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/models/V2UpdateResponse.kt @@ -35,6 +35,7 @@ class V2UpdateResponse private constructor( private val token: JsonField, private val accountTokens: JsonField>, + private val businessAccountTokens: JsonField>, private val cardTokens: JsonField>, private val currentVersion: JsonField, private val draftVersion: JsonField, @@ -53,6 +54,9 @@ private constructor( @JsonProperty("account_tokens") @ExcludeMissing accountTokens: JsonField> = JsonMissing.of(), + @JsonProperty("business_account_tokens") + @ExcludeMissing + businessAccountTokens: JsonField> = JsonMissing.of(), @JsonProperty("card_tokens") @ExcludeMissing cardTokens: JsonField> = JsonMissing.of(), @@ -77,6 +81,7 @@ private constructor( ) : this( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -105,6 +110,15 @@ private constructor( */ fun accountTokens(): List = accountTokens.getRequired("account_tokens") + /** + * Business Account tokens to which the Auth Rule applies. + * + * @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 businessAccountTokens(): List = + businessAccountTokens.getRequired("business_account_tokens") + /** * Card tokens to which the Auth Rule applies. * @@ -126,7 +140,7 @@ private constructor( fun draftVersion(): Optional = draftVersion.getOptional("draft_version") /** - * The type of event stream the Auth rule applies to. + * The event stream during which the rule will be evaluated. * * @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). @@ -158,12 +172,13 @@ private constructor( fun state(): AuthRuleState = state.getRequired("state") /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION 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). @@ -195,6 +210,16 @@ private constructor( @ExcludeMissing fun _accountTokens(): JsonField> = accountTokens + /** + * Returns the raw JSON value of [businessAccountTokens]. + * + * Unlike [businessAccountTokens], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("business_account_tokens") + @ExcludeMissing + fun _businessAccountTokens(): JsonField> = businessAccountTokens + /** * Returns the raw JSON value of [cardTokens]. * @@ -292,6 +317,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -310,6 +336,7 @@ private constructor( private var token: JsonField? = null private var accountTokens: JsonField>? = null + private var businessAccountTokens: JsonField>? = null private var cardTokens: JsonField>? = null private var currentVersion: JsonField? = null private var draftVersion: JsonField? = null @@ -325,6 +352,8 @@ private constructor( internal fun from(v2UpdateResponse: V2UpdateResponse) = apply { token = v2UpdateResponse.token accountTokens = v2UpdateResponse.accountTokens.map { it.toMutableList() } + businessAccountTokens = + v2UpdateResponse.businessAccountTokens.map { it.toMutableList() } cardTokens = v2UpdateResponse.cardTokens.map { it.toMutableList() } currentVersion = v2UpdateResponse.currentVersion draftVersion = v2UpdateResponse.draftVersion @@ -374,6 +403,33 @@ private constructor( } } + /** Business Account tokens to which the Auth Rule applies. */ + fun businessAccountTokens(businessAccountTokens: List) = + businessAccountTokens(JsonField.of(businessAccountTokens)) + + /** + * Sets [Builder.businessAccountTokens] to an arbitrary JSON value. + * + * You should usually call [Builder.businessAccountTokens] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun businessAccountTokens(businessAccountTokens: JsonField>) = apply { + this.businessAccountTokens = businessAccountTokens.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [businessAccountTokens]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addBusinessAccountToken(businessAccountToken: String) = apply { + businessAccountTokens = + (businessAccountTokens ?: JsonField.of(mutableListOf())).also { + checkKnown("businessAccountTokens", it).add(businessAccountToken) + } + } + /** Card tokens to which the Auth Rule applies. */ fun cardTokens(cardTokens: List) = cardTokens(JsonField.of(cardTokens)) @@ -436,7 +492,7 @@ private constructor( this.draftVersion = draftVersion } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ fun eventStream(eventStream: EventStream) = eventStream(JsonField.of(eventStream)) /** @@ -491,12 +547,13 @@ private constructor( fun state(state: JsonField) = apply { this.state = state } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event + * streams, the effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ fun type(type: AuthRuleType) = type(JsonField.of(type)) @@ -564,6 +621,7 @@ private constructor( * ```java * .token() * .accountTokens() + * .businessAccountTokens() * .cardTokens() * .currentVersion() * .draftVersion() @@ -580,6 +638,9 @@ private constructor( V2UpdateResponse( checkRequired("token", token), checkRequired("accountTokens", accountTokens).map { it.toImmutable() }, + checkRequired("businessAccountTokens", businessAccountTokens).map { + it.toImmutable() + }, checkRequired("cardTokens", cardTokens).map { it.toImmutable() }, checkRequired("currentVersion", currentVersion), checkRequired("draftVersion", draftVersion), @@ -602,6 +663,7 @@ private constructor( token() accountTokens() + businessAccountTokens() cardTokens() currentVersion().ifPresent { it.validate() } draftVersion().ifPresent { it.validate() } @@ -631,6 +693,7 @@ private constructor( internal fun validity(): Int = (if (token.asKnown().isPresent) 1 else 0) + (accountTokens.asKnown().getOrNull()?.size ?: 0) + + (businessAccountTokens.asKnown().getOrNull()?.size ?: 0) + (cardTokens.asKnown().getOrNull()?.size ?: 0) + (currentVersion.asKnown().getOrNull()?.validity() ?: 0) + (draftVersion.asKnown().getOrNull()?.validity() ?: 0) + @@ -767,6 +830,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -861,6 +935,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -875,6 +951,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -883,6 +963,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -894,6 +976,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -904,6 +989,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -937,6 +1024,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -975,6 +1068,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -988,7 +1085,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -997,6 +1095,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1007,6 +1106,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1028,6 +1129,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1046,6 +1152,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1080,6 +1190,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1112,11 +1232,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1266,6 +2811,17 @@ private constructor( fun parameters(conditional3dsAction: Conditional3dsActionParameters) = parameters(Parameters.ofConditional3dsAction(conditional3dsAction)) + /** + * Alias for calling [parameters] with + * `Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction)`. + */ + fun parameters( + conditionalAuthorizationAction: Parameters.ConditionalAuthorizationActionParameters + ) = + parameters( + Parameters.ofConditionalAuthorizationAction(conditionalAuthorizationAction) + ) + /** * The version of the rule, this is incremented whenever the rule's parameters change. */ @@ -1360,6 +2916,8 @@ private constructor( private val velocityLimitParams: VelocityLimitParams? = null, private val merchantLock: MerchantLockParameters? = null, private val conditional3dsAction: Conditional3dsActionParameters? = null, + private val conditionalAuthorizationAction: ConditionalAuthorizationActionParameters? = + null, private val _json: JsonValue? = null, ) { @@ -1374,6 +2932,10 @@ private constructor( fun conditional3dsAction(): Optional = Optional.ofNullable(conditional3dsAction) + fun conditionalAuthorizationAction(): + Optional = + Optional.ofNullable(conditionalAuthorizationAction) + fun isConditionalBlock(): Boolean = conditionalBlock != null fun isVelocityLimitParams(): Boolean = velocityLimitParams != null @@ -1382,6 +2944,8 @@ private constructor( fun isConditional3dsAction(): Boolean = conditional3dsAction != null + fun isConditionalAuthorizationAction(): Boolean = conditionalAuthorizationAction != null + fun asConditionalBlock(): ConditionalBlockParameters = conditionalBlock.getOrThrow("conditionalBlock") @@ -1393,6 +2957,9 @@ private constructor( fun asConditional3dsAction(): Conditional3dsActionParameters = conditional3dsAction.getOrThrow("conditional3dsAction") + fun asConditionalAuthorizationAction(): ConditionalAuthorizationActionParameters = + conditionalAuthorizationAction.getOrThrow("conditionalAuthorizationAction") + fun _json(): Optional = Optional.ofNullable(_json) fun accept(visitor: Visitor): T = @@ -1403,6 +2970,8 @@ private constructor( merchantLock != null -> visitor.visitMerchantLock(merchantLock) conditional3dsAction != null -> visitor.visitConditional3dsAction(conditional3dsAction) + conditionalAuthorizationAction != null -> + visitor.visitConditionalAuthorizationAction(conditionalAuthorizationAction) else -> visitor.unknown(_json) } @@ -1436,6 +3005,12 @@ private constructor( ) { conditional3dsAction.validate() } + + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) { + conditionalAuthorizationAction.validate() + } } ) validated = true @@ -1474,6 +3049,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ) = conditional3dsAction.validity() + override fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = conditionalAuthorizationAction.validity() + override fun unknown(json: JsonValue?) = 0 } ) @@ -1487,7 +3066,8 @@ private constructor( conditionalBlock == other.conditionalBlock && velocityLimitParams == other.velocityLimitParams && merchantLock == other.merchantLock && - conditional3dsAction == other.conditional3dsAction + conditional3dsAction == other.conditional3dsAction && + conditionalAuthorizationAction == other.conditionalAuthorizationAction } override fun hashCode(): Int = @@ -1496,6 +3076,7 @@ private constructor( velocityLimitParams, merchantLock, conditional3dsAction, + conditionalAuthorizationAction, ) override fun toString(): String = @@ -1506,6 +3087,8 @@ private constructor( merchantLock != null -> "Parameters{merchantLock=$merchantLock}" conditional3dsAction != null -> "Parameters{conditional3dsAction=$conditional3dsAction}" + conditionalAuthorizationAction != null -> + "Parameters{conditionalAuthorizationAction=$conditionalAuthorizationAction}" _json != null -> "Parameters{_unknown=$_json}" else -> throw IllegalStateException("Invalid Parameters") } @@ -1527,6 +3110,11 @@ private constructor( @JvmStatic fun ofConditional3dsAction(conditional3dsAction: Conditional3dsActionParameters) = Parameters(conditional3dsAction = conditional3dsAction) + + @JvmStatic + fun ofConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ) = Parameters(conditionalAuthorizationAction = conditionalAuthorizationAction) } /** @@ -1545,6 +3133,10 @@ private constructor( conditional3dsAction: Conditional3dsActionParameters ): T + fun visitConditionalAuthorizationAction( + conditionalAuthorizationAction: ConditionalAuthorizationActionParameters + ): T + /** * Maps an unknown variant of [Parameters] to a value of type [T]. * @@ -1579,6 +3171,16 @@ private constructor( jacksonTypeRef(), ) ?.let { Parameters(conditional3dsAction = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + Parameters( + conditionalAuthorizationAction = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1611,11 +3213,1436 @@ private constructor( value.merchantLock != null -> generator.writeObject(value.merchantLock) value.conditional3dsAction != null -> generator.writeObject(value.conditional3dsAction) + value.conditionalAuthorizationAction != null -> + generator.writeObject(value.conditionalAuthorizationAction) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Parameters") } } } + + class ConditionalAuthorizationActionParameters + private constructor( + private val action: JsonField, + private val conditions: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("action") + @ExcludeMissing + action: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField> = JsonMissing.of(), + ) : this(action, conditions, mutableMapOf()) + + /** + * The action to take if the conditions are met. + * + * @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 action(): Action = action.getRequired("action") + + /** + * @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 conditions(): List = conditions.getRequired("conditions") + + /** + * Returns the raw JSON value of [action]. + * + * Unlike [action], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("action") @ExcludeMissing fun _action(): JsonField = action + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField> = conditions + + @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 + * [ConditionalAuthorizationActionParameters]. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ConditionalAuthorizationActionParameters]. */ + class Builder internal constructor() { + + private var action: JsonField? = null + private var conditions: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from( + conditionalAuthorizationActionParameters: + ConditionalAuthorizationActionParameters + ) = apply { + action = conditionalAuthorizationActionParameters.action + conditions = + conditionalAuthorizationActionParameters.conditions.map { + it.toMutableList() + } + additionalProperties = + conditionalAuthorizationActionParameters.additionalProperties + .toMutableMap() + } + + /** The action to take if the conditions are met. */ + fun action(action: Action) = action(JsonField.of(action)) + + /** + * Sets [Builder.action] to an arbitrary JSON value. + * + * You should usually call [Builder.action] with a well-typed [Action] value + * instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun action(action: JsonField) = apply { this.action = action } + + fun conditions(conditions: List) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField>) = apply { + this.conditions = conditions.map { it.toMutableList() } + } + + /** + * Adds a single [Condition] to [conditions]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addCondition(condition: Condition) = apply { + conditions = + (conditions ?: JsonField.of(mutableListOf())).also { + checkKnown("conditions", it).add(condition) + } + } + + 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 [ConditionalAuthorizationActionParameters]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .action() + * .conditions() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ConditionalAuthorizationActionParameters = + ConditionalAuthorizationActionParameters( + checkRequired("action", action), + checkRequired("conditions", conditions).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): ConditionalAuthorizationActionParameters = apply { + if (validated) { + return@apply + } + + action().validate() + conditions().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 = + (action.asKnown().getOrNull()?.validity() ?: 0) + + (conditions.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + /** The action to take if the conditions are met. */ + class Action + @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 DECLINE = of("DECLINE") + + @JvmField val CHALLENGE = of("CHALLENGE") + + @JvmStatic fun of(value: String) = Action(JsonField.of(value)) + } + + /** An enum containing [Action]'s known values. */ + enum class Known { + DECLINE, + CHALLENGE, + } + + /** + * An enum containing [Action]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Action] 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 { + DECLINE, + CHALLENGE, + /** + * An enum member indicating that [Action] 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) { + DECLINE -> Value.DECLINE + CHALLENGE -> Value.CHALLENGE + 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) { + DECLINE -> Known.DECLINE + CHALLENGE -> Known.CHALLENGE + else -> throw LithicInvalidDataException("Unknown Action: $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(): Action = 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 Action && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Condition + private constructor( + private val attribute: JsonField, + private val operation: JsonField, + private val value: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("attribute") + @ExcludeMissing + attribute: JsonField = JsonMissing.of(), + @JsonProperty("operation") + @ExcludeMissing + operation: JsonField = JsonMissing.of(), + @JsonProperty("value") + @ExcludeMissing + value: JsonField = JsonMissing.of(), + ) : this(attribute, operation, value, mutableMapOf()) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun attribute(): Optional = attribute.getOptional("attribute") + + /** + * The operation to apply to the attribute + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun operation(): Optional = operation.getOptional("operation") + + /** + * A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` + * + * @throws LithicInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun value(): Optional = value.getOptional("value") + + /** + * Returns the raw JSON value of [attribute]. + * + * Unlike [attribute], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("attribute") + @ExcludeMissing + fun _attribute(): JsonField = attribute + + /** + * Returns the raw JSON value of [operation]. + * + * Unlike [operation], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("operation") + @ExcludeMissing + fun _operation(): JsonField = operation + + /** + * Returns the raw JSON value of [value]. + * + * Unlike [value], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("value") @ExcludeMissing fun _value(): JsonField = value + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Condition]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Condition]. */ + class Builder internal constructor() { + + private var attribute: JsonField = JsonMissing.of() + private var operation: JsonField = JsonMissing.of() + private var value: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = + mutableMapOf() + + @JvmSynthetic + internal fun from(condition: Condition) = apply { + attribute = condition.attribute + operation = condition.operation + value = condition.value + additionalProperties = condition.additionalProperties.toMutableMap() + } + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to + * classify a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) + * all ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT + * for Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant + * currency of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card + * acceptor (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, + * `ICC`, `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, + * `SECURE_CARDLESS`, `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or + * `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This + * is the amount the issuer should authorize against unless the issuer is + * paying the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated + * with a given authorization. Scores are on a range of 0-999, with 0 + * representing the lowest risk and 999 representing the highest risk. For + * Visa transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in + * the trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in + * the trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in + * the trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the + * transaction. Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are + * `NOT_SET`, `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates + * the source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + fun attribute(attribute: Attribute) = attribute(JsonField.of(attribute)) + + /** + * Sets [Builder.attribute] to an arbitrary JSON value. + * + * You should usually call [Builder.attribute] with a well-typed [Attribute] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun attribute(attribute: JsonField) = apply { + this.attribute = attribute + } + + /** The operation to apply to the attribute */ + fun operation(operation: Operation) = operation(JsonField.of(operation)) + + /** + * Sets [Builder.operation] to an arbitrary JSON value. + * + * You should usually call [Builder.operation] with a well-typed [Operation] + * value instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun operation(operation: JsonField) = apply { + this.operation = operation + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun value(value: Value) = value(JsonField.of(value)) + + /** + * Sets [Builder.value] to an arbitrary JSON value. + * + * You should usually call [Builder.value] with a well-typed [Value] value + * instead. This method is primarily for setting the field to an + * undocumented or not yet supported value. + */ + fun value(value: JsonField) = apply { this.value = value } + + /** Alias for calling [value] with `Value.ofRegex(regex)`. */ + fun value(regex: String) = value(Value.ofRegex(regex)) + + /** Alias for calling [value] with `Value.ofNumber(number)`. */ + fun value(number: Long) = value(Value.ofNumber(number)) + + /** + * Alias for calling [value] with `Value.ofListOfStrings(listOfStrings)`. + */ + fun valueOfListOfStrings(listOfStrings: List) = + value(Value.ofListOfStrings(listOfStrings)) + + 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 [Condition]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Condition = + Condition( + attribute, + operation, + value, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Condition = apply { + if (validated) { + return@apply + } + + attribute().ifPresent { it.validate() } + operation().ifPresent { it.validate() } + value().ifPresent { 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 = + (attribute.asKnown().getOrNull()?.validity() ?: 0) + + (operation.asKnown().getOrNull()?.validity() ?: 0) + + (value.asKnown().getOrNull()?.validity() ?: 0) + + /** + * The attribute to target. + * + * The following attributes may be targeted: + * - `MCC`: A four-digit number listed in ISO 18245. An MCC is used to classify + * a business by the types of goods or services it provides. + * - `COUNTRY`: Country of entity of card acceptor. Possible values are: (1) all + * ISO 3166-1 alpha-3 country codes, (2) QZZ for Kosovo, and (3) ANT for + * Netherlands Antilles. + * - `CURRENCY`: 3-character alphabetic ISO 4217 code for the merchant currency + * of the transaction. + * - `MERCHANT_ID`: Unique alphanumeric identifier for the payment card acceptor + * (merchant). + * - `DESCRIPTOR`: Short description of card acceptor. + * - `LIABILITY_SHIFT`: Indicates whether chargeback liability shift to the + * issuer applies to the transaction. Valid values are `NONE`, + * `3DS_AUTHENTICATED`, or `TOKEN_AUTHENTICATED`. + * - `PAN_ENTRY_MODE`: The method by which the cardholder's primary account + * number (PAN) was entered. Valid values are `AUTO_ENTRY`, `BAR_CODE`, + * `CONTACTLESS`, `ECOMMERCE`, `ERROR_KEYED`, `ERROR_MAGNETIC_STRIPE`, `ICC`, + * `KEY_ENTERED`, `MAGNETIC_STRIPE`, `MANUAL`, `OCR`, `SECURE_CARDLESS`, + * `UNSPECIFIED`, `UNKNOWN`, `CREDENTIAL_ON_FILE`, or `ECOMMERCE`. + * - `TRANSACTION_AMOUNT`: The base transaction amount (in cents) plus the + * acquirer fee field in the settlement/cardholder billing currency. This is + * the amount the issuer should authorize against unless the issuer is paying + * the acquirer fee on behalf of the cardholder. + * - `RISK_SCORE`: Network-provided score assessing risk level associated with a + * given authorization. Scores are on a range of 0-999, with 0 representing + * the lowest risk and 999 representing the highest risk. For Visa + * transactions, where the raw score has a range of 0-99, Lithic will + * normalize the score by multiplying the raw score by 10x. + * - `CARD_TRANSACTION_COUNT_15M`: The number of transactions on the card in the + * trailing 15 minutes before the authorization. + * - `CARD_TRANSACTION_COUNT_1H`: The number of transactions on the card in the + * trailing hour up and until the authorization. + * - `CARD_TRANSACTION_COUNT_24H`: The number of transactions on the card in the + * trailing 24 hours up and until the authorization. + * - `CARD_STATE`: The current state of the card associated with the + * transaction. Valid values are `CLOSED`, `OPEN`, `PAUSED`, + * `PENDING_ACTIVATION`, `PENDING_FULFILLMENT`. + * - `PIN_ENTERED`: Indicates whether a PIN was entered during the transaction. + * Valid values are `TRUE`, `FALSE`. + * - `PIN_STATUS`: The current state of card's PIN. Valid values are `NOT_SET`, + * `OK`, `BLOCKED`. + * - `WALLET_TYPE`: For transactions using a digital wallet token, indicates the + * source of the token. Valid values are `APPLE_PAY`, `GOOGLE_PAY`, + * `SAMSUNG_PAY`, `MASTERPASS`, `MERCHANT`, `OTHER`, `NONE`. + * - `TRANSACTION_INITIATOR`: The entity that initiated the transaction + * indicates the source of the token. Valid values are `CARDHOLDER`, + * `MERCHANT`, `UNKNOWN`. + */ + class Attribute + @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 MCC = of("MCC") + + @JvmField val COUNTRY = of("COUNTRY") + + @JvmField val CURRENCY = of("CURRENCY") + + @JvmField val MERCHANT_ID = of("MERCHANT_ID") + + @JvmField val DESCRIPTOR = of("DESCRIPTOR") + + @JvmField val LIABILITY_SHIFT = of("LIABILITY_SHIFT") + + @JvmField val PAN_ENTRY_MODE = of("PAN_ENTRY_MODE") + + @JvmField val TRANSACTION_AMOUNT = of("TRANSACTION_AMOUNT") + + @JvmField val RISK_SCORE = of("RISK_SCORE") + + @JvmField + val CARD_TRANSACTION_COUNT_15_M = of("CARD_TRANSACTION_COUNT_15M") + + @JvmField + val CARD_TRANSACTION_COUNT_1_H = of("CARD_TRANSACTION_COUNT_1H") + + @JvmField + val CARD_TRANSACTION_COUNT_24_H = of("CARD_TRANSACTION_COUNT_24H") + + @JvmField val CARD_STATE = of("CARD_STATE") + + @JvmField val PIN_ENTERED = of("PIN_ENTERED") + + @JvmField val PIN_STATUS = of("PIN_STATUS") + + @JvmField val WALLET_TYPE = of("WALLET_TYPE") + + @JvmField val TRANSACTION_INITIATOR = of("TRANSACTION_INITIATOR") + + @JvmStatic fun of(value: String) = Attribute(JsonField.of(value)) + } + + /** An enum containing [Attribute]'s known values. */ + enum class Known { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + } + + /** + * An enum containing [Attribute]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Attribute] 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 { + MCC, + COUNTRY, + CURRENCY, + MERCHANT_ID, + DESCRIPTOR, + LIABILITY_SHIFT, + PAN_ENTRY_MODE, + TRANSACTION_AMOUNT, + RISK_SCORE, + CARD_TRANSACTION_COUNT_15_M, + CARD_TRANSACTION_COUNT_1_H, + CARD_TRANSACTION_COUNT_24_H, + CARD_STATE, + PIN_ENTERED, + PIN_STATUS, + WALLET_TYPE, + TRANSACTION_INITIATOR, + /** + * An enum member indicating that [Attribute] 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) { + MCC -> Value.MCC + COUNTRY -> Value.COUNTRY + CURRENCY -> Value.CURRENCY + MERCHANT_ID -> Value.MERCHANT_ID + DESCRIPTOR -> Value.DESCRIPTOR + LIABILITY_SHIFT -> Value.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Value.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Value.TRANSACTION_AMOUNT + RISK_SCORE -> Value.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Value.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Value.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Value.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Value.CARD_STATE + PIN_ENTERED -> Value.PIN_ENTERED + PIN_STATUS -> Value.PIN_STATUS + WALLET_TYPE -> Value.WALLET_TYPE + TRANSACTION_INITIATOR -> Value.TRANSACTION_INITIATOR + 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) { + MCC -> Known.MCC + COUNTRY -> Known.COUNTRY + CURRENCY -> Known.CURRENCY + MERCHANT_ID -> Known.MERCHANT_ID + DESCRIPTOR -> Known.DESCRIPTOR + LIABILITY_SHIFT -> Known.LIABILITY_SHIFT + PAN_ENTRY_MODE -> Known.PAN_ENTRY_MODE + TRANSACTION_AMOUNT -> Known.TRANSACTION_AMOUNT + RISK_SCORE -> Known.RISK_SCORE + CARD_TRANSACTION_COUNT_15_M -> Known.CARD_TRANSACTION_COUNT_15_M + CARD_TRANSACTION_COUNT_1_H -> Known.CARD_TRANSACTION_COUNT_1_H + CARD_TRANSACTION_COUNT_24_H -> Known.CARD_TRANSACTION_COUNT_24_H + CARD_STATE -> Known.CARD_STATE + PIN_ENTERED -> Known.PIN_ENTERED + PIN_STATUS -> Known.PIN_STATUS + WALLET_TYPE -> Known.WALLET_TYPE + TRANSACTION_INITIATOR -> Known.TRANSACTION_INITIATOR + else -> + throw LithicInvalidDataException("Unknown Attribute: $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(): Attribute = 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 Attribute && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** The operation to apply to the attribute */ + class Operation + @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 IS_ONE_OF = of("IS_ONE_OF") + + @JvmField val IS_NOT_ONE_OF = of("IS_NOT_ONE_OF") + + @JvmField val MATCHES = of("MATCHES") + + @JvmField val DOES_NOT_MATCH = of("DOES_NOT_MATCH") + + @JvmField val IS_EQUAL_TO = of("IS_EQUAL_TO") + + @JvmField val IS_NOT_EQUAL_TO = of("IS_NOT_EQUAL_TO") + + @JvmField val IS_GREATER_THAN = of("IS_GREATER_THAN") + + @JvmField + val IS_GREATER_THAN_OR_EQUAL_TO = of("IS_GREATER_THAN_OR_EQUAL_TO") + + @JvmField val IS_LESS_THAN = of("IS_LESS_THAN") + + @JvmField val IS_LESS_THAN_OR_EQUAL_TO = of("IS_LESS_THAN_OR_EQUAL_TO") + + @JvmStatic fun of(value: String) = Operation(JsonField.of(value)) + } + + /** An enum containing [Operation]'s known values. */ + enum class Known { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + } + + /** + * An enum containing [Operation]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [Operation] 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 { + IS_ONE_OF, + IS_NOT_ONE_OF, + MATCHES, + DOES_NOT_MATCH, + IS_EQUAL_TO, + IS_NOT_EQUAL_TO, + IS_GREATER_THAN, + IS_GREATER_THAN_OR_EQUAL_TO, + IS_LESS_THAN, + IS_LESS_THAN_OR_EQUAL_TO, + /** + * An enum member indicating that [Operation] 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) { + IS_ONE_OF -> Value.IS_ONE_OF + IS_NOT_ONE_OF -> Value.IS_NOT_ONE_OF + MATCHES -> Value.MATCHES + DOES_NOT_MATCH -> Value.DOES_NOT_MATCH + IS_EQUAL_TO -> Value.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Value.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Value.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Value.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Value.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Value.IS_LESS_THAN_OR_EQUAL_TO + 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) { + IS_ONE_OF -> Known.IS_ONE_OF + IS_NOT_ONE_OF -> Known.IS_NOT_ONE_OF + MATCHES -> Known.MATCHES + DOES_NOT_MATCH -> Known.DOES_NOT_MATCH + IS_EQUAL_TO -> Known.IS_EQUAL_TO + IS_NOT_EQUAL_TO -> Known.IS_NOT_EQUAL_TO + IS_GREATER_THAN -> Known.IS_GREATER_THAN + IS_GREATER_THAN_OR_EQUAL_TO -> Known.IS_GREATER_THAN_OR_EQUAL_TO + IS_LESS_THAN -> Known.IS_LESS_THAN + IS_LESS_THAN_OR_EQUAL_TO -> Known.IS_LESS_THAN_OR_EQUAL_TO + else -> + throw LithicInvalidDataException("Unknown Operation: $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(): Operation = 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 Operation && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JsonDeserialize(using = Value.Deserializer::class) + @JsonSerialize(using = Value.Serializer::class) + class Value + private constructor( + private val regex: String? = null, + private val number: Long? = null, + private val listOfStrings: List? = null, + private val _json: JsonValue? = null, + ) { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun regex(): Optional = Optional.ofNullable(regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun number(): Optional = Optional.ofNullable(number) + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun listOfStrings(): Optional> = + Optional.ofNullable(listOfStrings) + + fun isRegex(): Boolean = regex != null + + fun isNumber(): Boolean = number != null + + fun isListOfStrings(): Boolean = listOfStrings != null + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun asRegex(): String = regex.getOrThrow("regex") + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun asNumber(): Long = number.getOrThrow("number") + + /** An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` */ + fun asListOfStrings(): List = + listOfStrings.getOrThrow("listOfStrings") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + regex != null -> visitor.visitRegex(regex) + number != null -> visitor.visitNumber(number) + listOfStrings != null -> visitor.visitListOfStrings(listOfStrings) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Value = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitRegex(regex: String) {} + + override fun visitNumber(number: Long) {} + + override fun visitListOfStrings(listOfStrings: List) {} + } + ) + 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 visitRegex(regex: String) = 1 + + override fun visitNumber(number: Long) = 1 + + override fun visitListOfStrings(listOfStrings: List) = + listOfStrings.size + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Value && + regex == other.regex && + number == other.number && + listOfStrings == other.listOfStrings + } + + override fun hashCode(): Int = Objects.hash(regex, number, listOfStrings) + + override fun toString(): String = + when { + regex != null -> "Value{regex=$regex}" + number != null -> "Value{number=$number}" + listOfStrings != null -> "Value{listOfStrings=$listOfStrings}" + _json != null -> "Value{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Value") + } + + companion object { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + @JvmStatic fun ofRegex(regex: String) = Value(regex = regex) + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + @JvmStatic fun ofNumber(number: Long) = Value(number = number) + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + @JvmStatic + fun ofListOfStrings(listOfStrings: List) = + Value(listOfStrings = listOfStrings.toImmutable()) + } + + /** + * An interface that defines how to map each variant of [Value] to a value + * of type [T]. + */ + interface Visitor { + + /** A regex string, to be used with `MATCHES` or `DOES_NOT_MATCH` */ + fun visitRegex(regex: String): T + + /** + * A number, to be used with `IS_GREATER_THAN`, + * `IS_GREATER_THAN_OR_EQUAL_TO`, `IS_LESS_THAN`, + * `IS_LESS_THAN_OR_EQUAL_TO`, `IS_EQUAL_TO`, or `IS_NOT_EQUAL_TO` + */ + fun visitNumber(number: Long): T + + /** + * An array of strings, to be used with `IS_ONE_OF` or `IS_NOT_ONE_OF` + */ + fun visitListOfStrings(listOfStrings: List): T + + /** + * Maps an unknown variant of [Value] to a value of type [T]. + * + * An instance of [Value] 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 Value: $json") + } + } + + internal class Deserializer : BaseDeserializer(Value::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Value { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Value(regex = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Value(number = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>()) + ?.let { Value(listOfStrings = 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 object). + 0 -> Value(_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(Value::class) { + + override fun serialize( + value: Value, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.regex != null -> generator.writeObject(value.regex) + value.number != null -> generator.writeObject(value.number) + value.listOfStrings != null -> + generator.writeObject(value.listOfStrings) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Value") + } + } + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Condition && + attribute == other.attribute && + operation == other.operation && + value == other.value && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(attribute, operation, value, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Condition{attribute=$attribute, operation=$operation, value=$value, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is ConditionalAuthorizationActionParameters && + action == other.action && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(action, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "ConditionalAuthorizationActionParameters{action=$action, conditions=$conditions, additionalProperties=$additionalProperties}" + } } override fun equals(other: Any?): Boolean { @@ -1639,7 +4666,7 @@ private constructor( "DraftVersion{parameters=$parameters, version=$version, additionalProperties=$additionalProperties}" } - /** The type of event stream the Auth rule applies to. */ + /** The event stream during which the rule will be evaluated. */ class EventStream @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1899,12 +4926,13 @@ private constructor( } /** - * The type of Auth Rule. Effectively determines the event stream during which it will be - * evaluated. + * 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 several event streams, the + * effective one is defined by the separate `event_stream` field. * - `CONDITIONAL_BLOCK`: AUTHORIZATION event stream. * - `VELOCITY_LIMIT`: AUTHORIZATION event stream. * - `MERCHANT_LOCK`: AUTHORIZATION event stream. - * - `CONDITIONAL_3DS_ACTION`: THREE_DS_AUTHENTICATION event stream. + * - `CONDITIONAL_ACTION`: AUTHORIZATION or THREE_DS_AUTHENTICATION event stream. */ class AuthRuleType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1927,7 +4955,7 @@ private constructor( @JvmField val MERCHANT_LOCK = of("MERCHANT_LOCK") - @JvmField val CONDITIONAL_3DS_ACTION = of("CONDITIONAL_3DS_ACTION") + @JvmField val CONDITIONAL_ACTION = of("CONDITIONAL_ACTION") @JvmStatic fun of(value: String) = AuthRuleType(JsonField.of(value)) } @@ -1937,7 +4965,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, } /** @@ -1953,7 +4981,7 @@ private constructor( CONDITIONAL_BLOCK, VELOCITY_LIMIT, MERCHANT_LOCK, - CONDITIONAL_3DS_ACTION, + CONDITIONAL_ACTION, /** * An enum member indicating that [AuthRuleType] was instantiated with an unknown value. */ @@ -1972,7 +5000,7 @@ private constructor( CONDITIONAL_BLOCK -> Value.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Value.VELOCITY_LIMIT MERCHANT_LOCK -> Value.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Value.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Value.CONDITIONAL_ACTION else -> Value._UNKNOWN } @@ -1990,7 +5018,7 @@ private constructor( CONDITIONAL_BLOCK -> Known.CONDITIONAL_BLOCK VELOCITY_LIMIT -> Known.VELOCITY_LIMIT MERCHANT_LOCK -> Known.MERCHANT_LOCK - CONDITIONAL_3DS_ACTION -> Known.CONDITIONAL_3DS_ACTION + CONDITIONAL_ACTION -> Known.CONDITIONAL_ACTION else -> throw LithicInvalidDataException("Unknown AuthRuleType: $value") } @@ -2054,6 +5082,7 @@ private constructor( return other is V2UpdateResponse && token == other.token && accountTokens == other.accountTokens && + businessAccountTokens == other.businessAccountTokens && cardTokens == other.cardTokens && currentVersion == other.currentVersion && draftVersion == other.draftVersion && @@ -2070,6 +5099,7 @@ private constructor( Objects.hash( token, accountTokens, + businessAccountTokens, cardTokens, currentVersion, draftVersion, @@ -2086,5 +5116,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "V2UpdateResponse{token=$token, accountTokens=$accountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" + "V2UpdateResponse{token=$token, accountTokens=$accountTokens, businessAccountTokens=$businessAccountTokens, cardTokens=$cardTokens, currentVersion=$currentVersion, draftVersion=$draftVersion, eventStream=$eventStream, name=$name, programLevel=$programLevel, state=$state, type=$type, excludedCardTokens=$excludedCardTokens, additionalProperties=$additionalProperties}" } diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/authRules/v2/BacktestServiceAsync.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/authRules/v2/BacktestServiceAsync.kt index 3dad5de19..5a73a0a68 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/authRules/v2/BacktestServiceAsync.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/async/authRules/v2/BacktestServiceAsync.kt @@ -42,13 +42,13 @@ interface BacktestServiceAsync { * request backtest reports on-demand through the * `/v2/auth_rules/{auth_rule_token}/backtests/{auth_rule_backtest_token}` endpoint. * - * Lithic currently supports backtesting for `CONDITIONAL_BLOCK` / `CONDITIONAL_3DS_ACTION` - * rules. Backtesting for `VELOCITY_LIMIT` rules is generally not supported. In specific cases - * (i.e. where Lithic has pre-calculated the requested velocity metrics for historical - * transactions), a backtest may be feasible. However, such cases are uncommon and customers - * should not anticipate support for velocity backtests under most configurations. If a - * historical transaction does not feature the required inputs to evaluate the rule, then it - * will not be included in the final backtest report. + * Lithic currently supports backtesting for `CONDITIONAL_BLOCK` / `CONDITIONAL_ACTION` rules. + * Backtesting for `VELOCITY_LIMIT` rules is generally not supported. In specific cases (i.e. + * where Lithic has pre-calculated the requested velocity metrics for historical transactions), + * a backtest may be feasible. However, such cases are uncommon and customers should not + * anticipate support for velocity backtests under most configurations. If a historical + * transaction does not feature the required inputs to evaluate the rule, then it will not be + * included in the final backtest report. */ fun create(authRuleToken: String): CompletableFuture = create(authRuleToken, AuthRuleV2BacktestCreateParams.none()) diff --git a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/authRules/v2/BacktestService.kt b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/authRules/v2/BacktestService.kt index 009bf6e99..16f75e0c6 100644 --- a/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/authRules/v2/BacktestService.kt +++ b/lithic-java-core/src/main/kotlin/com/lithic/api/services/blocking/authRules/v2/BacktestService.kt @@ -42,13 +42,13 @@ interface BacktestService { * request backtest reports on-demand through the * `/v2/auth_rules/{auth_rule_token}/backtests/{auth_rule_backtest_token}` endpoint. * - * Lithic currently supports backtesting for `CONDITIONAL_BLOCK` / `CONDITIONAL_3DS_ACTION` - * rules. Backtesting for `VELOCITY_LIMIT` rules is generally not supported. In specific cases - * (i.e. where Lithic has pre-calculated the requested velocity metrics for historical - * transactions), a backtest may be feasible. However, such cases are uncommon and customers - * should not anticipate support for velocity backtests under most configurations. If a - * historical transaction does not feature the required inputs to evaluate the rule, then it - * will not be included in the final backtest report. + * Lithic currently supports backtesting for `CONDITIONAL_BLOCK` / `CONDITIONAL_ACTION` rules. + * Backtesting for `VELOCITY_LIMIT` rules is generally not supported. In specific cases (i.e. + * where Lithic has pre-calculated the requested velocity metrics for historical transactions), + * a backtest may be feasible. However, such cases are uncommon and customers should not + * anticipate support for velocity backtests under most configurations. If a historical + * transaction does not feature the required inputs to evaluate the rule, then it will not be + * included in the final backtest report. */ fun create(authRuleToken: String): BacktestCreateResponse = create(authRuleToken, AuthRuleV2BacktestCreateParams.none()) diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListParamsTest.kt index fe14ce921..5c1196679 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AccountActivityListParamsTest.kt @@ -20,9 +20,9 @@ internal class AccountActivityListParamsTest { .endingBefore("ending_before") .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .pageSize(1L) - .addResult(AccountActivityListParams.Result.APPROVED) + .result(AccountActivityListParams.Result.APPROVED) .startingAfter("starting_after") - .addStatus(AccountActivityListParams.Status.DECLINED) + .status(AccountActivityListParams.Status.DECLINED) .build() } @@ -38,9 +38,9 @@ internal class AccountActivityListParamsTest { .endingBefore("ending_before") .financialAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .pageSize(1L) - .addResult(AccountActivityListParams.Result.APPROVED) + .result(AccountActivityListParams.Result.APPROVED) .startingAfter("starting_after") - .addStatus(AccountActivityListParams.Status.DECLINED) + .status(AccountActivityListParams.Status.DECLINED) .build() val queryParams = params._queryParams() @@ -56,9 +56,9 @@ internal class AccountActivityListParamsTest { .put("ending_before", "ending_before") .put("financial_account_token", "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .put("page_size", "1") - .put("result", listOf("APPROVED").joinToString(",")) + .put("result", "APPROVED") .put("starting_after", "starting_after") - .put("status", listOf("DECLINED").joinToString(",")) + .put("status", "DECLINED") .build() ) } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ApplyParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ApplyParamsTest.kt index 5868f1025..bfc91d9f3 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ApplyParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ApplyParamsTest.kt @@ -14,6 +14,7 @@ internal class AuthRuleV2ApplyParamsTest { .body( AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) .build() @@ -25,9 +26,7 @@ internal class AuthRuleV2ApplyParamsTest { AuthRuleV2ApplyParams.builder() .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .body( - AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .build() + AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder().build() ) .build() @@ -44,6 +43,7 @@ internal class AuthRuleV2ApplyParamsTest { .body( AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) .build() @@ -55,8 +55,29 @@ internal class AuthRuleV2ApplyParamsTest { AuthRuleV2ApplyParams.Body.ofApplyAuthRuleRequestAccountTokens( AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) ) } + + @Test + fun bodyWithoutOptionalFields() { + val params = + AuthRuleV2ApplyParams.builder() + .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .body( + AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder().build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + AuthRuleV2ApplyParams.Body.ofApplyAuthRuleRequestAccountTokens( + AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder().build() + ) + ) + } } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2CreateParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2CreateParamsTest.kt index aae547b03..2405a7bb1 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2CreateParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2CreateParamsTest.kt @@ -13,6 +13,11 @@ internal class AuthRuleV2CreateParamsTest { .body( AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .eventStream( + AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.EventStream + .AUTHORIZATION + ) .name("name") .parameters( ConditionalBlockParameters.builder() @@ -41,6 +46,12 @@ internal class AuthRuleV2CreateParamsTest { .body( AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .eventStream( + AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens + .EventStream + .AUTHORIZATION + ) .name("name") .parameters( ConditionalBlockParameters.builder() @@ -69,6 +80,12 @@ internal class AuthRuleV2CreateParamsTest { AuthRuleV2CreateParams.Body.ofCreateAuthRuleRequestAccountTokens( AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .eventStream( + AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens + .EventStream + .AUTHORIZATION + ) .name("name") .parameters( ConditionalBlockParameters.builder() @@ -97,7 +114,6 @@ internal class AuthRuleV2CreateParamsTest { AuthRuleV2CreateParams.builder() .body( AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .parameters( ConditionalBlockParameters.builder() .addCondition(AuthRuleCondition.builder().build()) @@ -118,7 +134,6 @@ internal class AuthRuleV2CreateParamsTest { .isEqualTo( AuthRuleV2CreateParams.Body.ofCreateAuthRuleRequestAccountTokens( AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .parameters( ConditionalBlockParameters.builder() .addCondition(AuthRuleCondition.builder().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 b407c00c3..e41efc070 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 @@ -17,6 +17,7 @@ internal class AuthRuleV2ListPageResponseTest { V2ListResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2ListResponse.CurrentVersion.builder() @@ -66,6 +67,7 @@ internal class AuthRuleV2ListPageResponseTest { V2ListResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2ListResponse.CurrentVersion.builder() @@ -119,6 +121,7 @@ internal class AuthRuleV2ListPageResponseTest { V2ListResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2ListResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListParamsTest.kt index c946ab6c8..2585b8d02 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2ListParamsTest.kt @@ -12,6 +12,7 @@ internal class AuthRuleV2ListParamsTest { fun create() { AuthRuleV2ListParams.builder() .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .businessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .endingBefore("ending_before") .eventStream(AuthRuleV2ListParams.EventStream.AUTHORIZATION) @@ -26,6 +27,7 @@ internal class AuthRuleV2ListParamsTest { val params = AuthRuleV2ListParams.builder() .accountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .businessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .cardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .endingBefore("ending_before") .eventStream(AuthRuleV2ListParams.EventStream.AUTHORIZATION) @@ -40,6 +42,7 @@ internal class AuthRuleV2ListParamsTest { .isEqualTo( QueryParams.builder() .put("account_token", "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .put("business_account_token", "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .put("card_token", "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .put("ending_before", "ending_before") .put("event_stream", "AUTHORIZATION") diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2UpdateParamsTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2UpdateParamsTest.kt index 64a48e620..97ca0baba 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2UpdateParamsTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthRuleV2UpdateParamsTest.kt @@ -12,10 +12,9 @@ internal class AuthRuleV2UpdateParamsTest { AuthRuleV2UpdateParams.builder() .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .body( - AuthRuleV2UpdateParams.Body.AccountLevelRule.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + AuthRuleV2UpdateParams.Body.UnionMember0.builder() .name("name") - .state(AuthRuleV2UpdateParams.Body.AccountLevelRule.State.INACTIVE) + .state(AuthRuleV2UpdateParams.Body.UnionMember0.State.INACTIVE) .build() ) .build() @@ -26,7 +25,7 @@ internal class AuthRuleV2UpdateParamsTest { val params = AuthRuleV2UpdateParams.builder() .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .body(AuthRuleV2UpdateParams.Body.AccountLevelRule.builder().build()) + .body(AuthRuleV2UpdateParams.Body.UnionMember0.builder().build()) .build() assertThat(params._pathParam(0)).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") @@ -40,10 +39,9 @@ internal class AuthRuleV2UpdateParamsTest { AuthRuleV2UpdateParams.builder() .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .body( - AuthRuleV2UpdateParams.Body.AccountLevelRule.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + AuthRuleV2UpdateParams.Body.UnionMember0.builder() .name("name") - .state(AuthRuleV2UpdateParams.Body.AccountLevelRule.State.INACTIVE) + .state(AuthRuleV2UpdateParams.Body.UnionMember0.State.INACTIVE) .build() ) .build() @@ -52,11 +50,10 @@ internal class AuthRuleV2UpdateParamsTest { assertThat(body) .isEqualTo( - AuthRuleV2UpdateParams.Body.ofAccountLevelRule( - AuthRuleV2UpdateParams.Body.AccountLevelRule.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + AuthRuleV2UpdateParams.Body.ofUnionMember0( + AuthRuleV2UpdateParams.Body.UnionMember0.builder() .name("name") - .state(AuthRuleV2UpdateParams.Body.AccountLevelRule.State.INACTIVE) + .state(AuthRuleV2UpdateParams.Body.UnionMember0.State.INACTIVE) .build() ) ) @@ -67,15 +64,15 @@ internal class AuthRuleV2UpdateParamsTest { val params = AuthRuleV2UpdateParams.builder() .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .body(AuthRuleV2UpdateParams.Body.AccountLevelRule.builder().build()) + .body(AuthRuleV2UpdateParams.Body.UnionMember0.builder().build()) .build() val body = params._body() assertThat(body) .isEqualTo( - AuthRuleV2UpdateParams.Body.ofAccountLevelRule( - AuthRuleV2UpdateParams.Body.AccountLevelRule.builder().build() + AuthRuleV2UpdateParams.Body.ofUnionMember0( + AuthRuleV2UpdateParams.Body.UnionMember0.builder().build() ) ) } diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthenticationRetrieveResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthenticationRetrieveResponseTest.kt index cdddd75ba..fe059edde 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthenticationRetrieveResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/AuthenticationRetrieveResponseTest.kt @@ -53,10 +53,6 @@ internal class AuthenticationRetrieveResponseTest { .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) .merchant( AuthenticationRetrieveResponse.Merchant.builder() - .id("id") - .country("xxx") - .mcc("xxxx") - .name("name") .riskIndicator( AuthenticationRetrieveResponse.Merchant.RiskIndicator.builder() .deliveryEmailAddress("delivery_email_address") @@ -88,6 +84,10 @@ internal class AuthenticationRetrieveResponseTest { ) .build() ) + .id("id") + .country("xxx") + .mcc("xxxx") + .name("name") .build() ) .messageCategory( @@ -209,10 +209,6 @@ internal class AuthenticationRetrieveResponseTest { assertThat(authenticationRetrieveResponse.merchant()) .isEqualTo( AuthenticationRetrieveResponse.Merchant.builder() - .id("id") - .country("xxx") - .mcc("xxxx") - .name("name") .riskIndicator( AuthenticationRetrieveResponse.Merchant.RiskIndicator.builder() .deliveryEmailAddress("delivery_email_address") @@ -240,6 +236,10 @@ internal class AuthenticationRetrieveResponseTest { ) .build() ) + .id("id") + .country("xxx") + .mcc("xxxx") + .name("name") .build() ) assertThat(authenticationRetrieveResponse.messageCategory()) @@ -358,10 +358,6 @@ internal class AuthenticationRetrieveResponseTest { .created(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) .merchant( AuthenticationRetrieveResponse.Merchant.builder() - .id("id") - .country("xxx") - .mcc("xxxx") - .name("name") .riskIndicator( AuthenticationRetrieveResponse.Merchant.RiskIndicator.builder() .deliveryEmailAddress("delivery_email_address") @@ -393,6 +389,10 @@ internal class AuthenticationRetrieveResponseTest { ) .build() ) + .id("id") + .country("xxx") + .mcc("xxxx") + .name("name") .build() ) .messageCategory( diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ApplyResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ApplyResponseTest.kt index 2f9a62f35..51b9a2087 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ApplyResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ApplyResponseTest.kt @@ -16,6 +16,7 @@ internal class V2ApplyResponseTest { V2ApplyResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2ApplyResponse.CurrentVersion.builder() @@ -60,6 +61,8 @@ internal class V2ApplyResponseTest { assertThat(v2ApplyResponse.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2ApplyResponse.accountTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(v2ApplyResponse.businessAccountTokens()) + .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2ApplyResponse.cardTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2ApplyResponse.currentVersion()) @@ -113,6 +116,7 @@ internal class V2ApplyResponseTest { V2ApplyResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2ApplyResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2CreateResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2CreateResponseTest.kt index ece46b808..d808ef96a 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2CreateResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2CreateResponseTest.kt @@ -16,6 +16,7 @@ internal class V2CreateResponseTest { V2CreateResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2CreateResponse.CurrentVersion.builder() @@ -60,6 +61,8 @@ internal class V2CreateResponseTest { assertThat(v2CreateResponse.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2CreateResponse.accountTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(v2CreateResponse.businessAccountTokens()) + .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2CreateResponse.cardTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2CreateResponse.currentVersion()) @@ -114,6 +117,7 @@ internal class V2CreateResponseTest { V2CreateResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2CreateResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2DraftResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2DraftResponseTest.kt index 62dd2214f..d2422e23f 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2DraftResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2DraftResponseTest.kt @@ -16,6 +16,7 @@ internal class V2DraftResponseTest { V2DraftResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2DraftResponse.CurrentVersion.builder() @@ -60,6 +61,8 @@ internal class V2DraftResponseTest { assertThat(v2DraftResponse.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2DraftResponse.accountTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(v2DraftResponse.businessAccountTokens()) + .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2DraftResponse.cardTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2DraftResponse.currentVersion()) @@ -113,6 +116,7 @@ internal class V2DraftResponseTest { V2DraftResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2DraftResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ListResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ListResponseTest.kt index 3d1365756..9b74151b8 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ListResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2ListResponseTest.kt @@ -16,6 +16,7 @@ internal class V2ListResponseTest { V2ListResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2ListResponse.CurrentVersion.builder() @@ -60,6 +61,8 @@ internal class V2ListResponseTest { assertThat(v2ListResponse.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2ListResponse.accountTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(v2ListResponse.businessAccountTokens()) + .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2ListResponse.cardTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2ListResponse.currentVersion()) @@ -112,6 +115,7 @@ internal class V2ListResponseTest { V2ListResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2ListResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2PromoteResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2PromoteResponseTest.kt index f8380bce3..5493c7e7f 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2PromoteResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2PromoteResponseTest.kt @@ -16,6 +16,7 @@ internal class V2PromoteResponseTest { V2PromoteResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2PromoteResponse.CurrentVersion.builder() @@ -60,6 +61,8 @@ internal class V2PromoteResponseTest { assertThat(v2PromoteResponse.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2PromoteResponse.accountTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(v2PromoteResponse.businessAccountTokens()) + .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2PromoteResponse.cardTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2PromoteResponse.currentVersion()) @@ -114,6 +117,7 @@ internal class V2PromoteResponseTest { V2PromoteResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2PromoteResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveResponseTest.kt index 499094a38..4b34b1f79 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2RetrieveResponseTest.kt @@ -16,6 +16,7 @@ internal class V2RetrieveResponseTest { V2RetrieveResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2RetrieveResponse.CurrentVersion.builder() @@ -60,6 +61,8 @@ internal class V2RetrieveResponseTest { assertThat(v2RetrieveResponse.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2RetrieveResponse.accountTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(v2RetrieveResponse.businessAccountTokens()) + .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2RetrieveResponse.cardTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2RetrieveResponse.currentVersion()) @@ -114,6 +117,7 @@ internal class V2RetrieveResponseTest { V2RetrieveResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2RetrieveResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2UpdateResponseTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2UpdateResponseTest.kt index f64c11b27..2aaa93585 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2UpdateResponseTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/models/V2UpdateResponseTest.kt @@ -16,6 +16,7 @@ internal class V2UpdateResponseTest { V2UpdateResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2UpdateResponse.CurrentVersion.builder() @@ -60,6 +61,8 @@ internal class V2UpdateResponseTest { assertThat(v2UpdateResponse.token()).isEqualTo("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2UpdateResponse.accountTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + assertThat(v2UpdateResponse.businessAccountTokens()) + .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2UpdateResponse.cardTokens()) .containsExactly("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") assertThat(v2UpdateResponse.currentVersion()) @@ -114,6 +117,7 @@ internal class V2UpdateResponseTest { V2UpdateResponse.builder() .token("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .addCardToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .currentVersion( V2UpdateResponse.CurrentVersion.builder() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/authRules/V2ServiceAsyncTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/authRules/V2ServiceAsyncTest.kt index c1a932444..3db652d79 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/authRules/V2ServiceAsyncTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/async/authRules/V2ServiceAsyncTest.kt @@ -34,6 +34,12 @@ internal class V2ServiceAsyncTest { .body( AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .eventStream( + AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens + .EventStream + .AUTHORIZATION + ) .name("name") .parameters( ConditionalBlockParameters.builder() @@ -89,10 +95,9 @@ internal class V2ServiceAsyncTest { AuthRuleV2UpdateParams.builder() .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .body( - AuthRuleV2UpdateParams.Body.AccountLevelRule.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + AuthRuleV2UpdateParams.Body.UnionMember0.builder() .name("name") - .state(AuthRuleV2UpdateParams.Body.AccountLevelRule.State.INACTIVE) + .state(AuthRuleV2UpdateParams.Body.UnionMember0.State.INACTIVE) .build() ) .build() @@ -147,6 +152,7 @@ internal class V2ServiceAsyncTest { .body( AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) .build() diff --git a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/authRules/V2ServiceTest.kt b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/authRules/V2ServiceTest.kt index 4b7158ea0..63b6d21c2 100644 --- a/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/authRules/V2ServiceTest.kt +++ b/lithic-java-core/src/test/kotlin/com/lithic/api/services/blocking/authRules/V2ServiceTest.kt @@ -34,6 +34,12 @@ internal class V2ServiceTest { .body( AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .eventStream( + AuthRuleV2CreateParams.Body.CreateAuthRuleRequestAccountTokens + .EventStream + .AUTHORIZATION + ) .name("name") .parameters( ConditionalBlockParameters.builder() @@ -87,10 +93,9 @@ internal class V2ServiceTest { AuthRuleV2UpdateParams.builder() .authRuleToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .body( - AuthRuleV2UpdateParams.Body.AccountLevelRule.builder() - .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + AuthRuleV2UpdateParams.Body.UnionMember0.builder() .name("name") - .state(AuthRuleV2UpdateParams.Body.AccountLevelRule.State.INACTIVE) + .state(AuthRuleV2UpdateParams.Body.UnionMember0.State.INACTIVE) .build() ) .build() @@ -141,6 +146,7 @@ internal class V2ServiceTest { .body( AuthRuleV2ApplyParams.Body.ApplyAuthRuleRequestAccountTokens.builder() .addAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .addBusinessAccountToken("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) .build() From 35a75985112012e000c2040516af66b8b080767f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Sep 2025 16:44:58 +0000 Subject: [PATCH 2/2] release: 0.104.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 8 ++++++++ README.md | 10 +++++----- build.gradle.kts | 2 +- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 508a7081b..19c0e9cca 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.103.0" + ".": "0.104.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e96859fd2..1b01a30fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.104.0 (2025-09-09) + +Full Changelog: [v0.103.0...v0.104.0](https://github.com/lithic-com/lithic-java/compare/v0.103.0...v0.104.0) + +### Features + +* **api:** adds support for unpauseing external bank accounts ([1dadb0f](https://github.com/lithic-com/lithic-java/commit/1dadb0f3e894c3ab7c38bf263e6974e81381d971)) + ## 0.103.0 (2025-09-03) Full Changelog: [v0.102.2...v0.103.0](https://github.com/lithic-com/lithic-java/compare/v0.102.2...v0.103.0) diff --git a/README.md b/README.md index cef9e62fb..622f13707 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.103.0) -[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/0.103.0/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.103.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.104.0) +[![javadoc](https://javadoc.io/badge2/com.lithic.api/lithic-java/0.104.0/javadoc.svg)](https://javadoc.io/doc/com.lithic.api/lithic-java/0.104.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.103.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.104.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.103.0") +implementation("com.lithic.api:lithic-java:0.104.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.lithic.api:lithic-java:0.103.0") com.lithic.api lithic-java - 0.103.0 + 0.104.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index c51a2cf97..f72139c39 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.lithic.api" - version = "0.103.0" // x-release-please-version + version = "0.104.0" // x-release-please-version } subprojects {