Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .stats.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
configured_endpoints: 150
configured_endpoints: 149
226 changes: 226 additions & 0 deletions courier-java-core/src/main/kotlin/com/courier/models/Apn.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// File generated from our OpenAPI spec by Stainless.

package com.courier.models

import com.courier.core.BaseDeserializer
import com.courier.core.BaseSerializer
import com.courier.core.JsonValue
import com.courier.core.allMaxBy
import com.courier.core.getOrThrow
import com.courier.errors.CourierInvalidDataException
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.ObjectCodec
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
import com.fasterxml.jackson.databind.annotation.JsonSerialize
import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import java.util.Objects
import java.util.Optional

/**
* Apple Push Notification device tokens. Supply either a single `token` or a `tokens` value. A bare
* string is rejected by the provider — the token must be wrapped in this object.
*/
@JsonDeserialize(using = Apn.Deserializer::class)
@JsonSerialize(using = Apn.Serializer::class)
class Apn
private constructor(
private val token: Token? = null,
private val multipleTokens: MultipleTokens? = null,
private val _json: JsonValue? = null,
) {

fun token(): Optional<Token> = Optional.ofNullable(token)

fun multipleTokens(): Optional<MultipleTokens> = Optional.ofNullable(multipleTokens)

fun isToken(): Boolean = token != null

fun isMultipleTokens(): Boolean = multipleTokens != null

fun asToken(): Token = token.getOrThrow("token")

fun asMultipleTokens(): MultipleTokens = multipleTokens.getOrThrow("multipleTokens")

fun _json(): Optional<JsonValue> = Optional.ofNullable(_json)

/**
* Maps this instance's current variant to a value of type [T] using the given [visitor].
*
* Note that this method is _not_ forwards compatible with new variants from the API, unless
* [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the
* SDK gracefully, consider overriding [Visitor.unknown]:
* ```java
* import com.courier.core.JsonValue;
* import java.util.Optional;
*
* Optional<String> result = apn.accept(new Apn.Visitor<Optional<String>>() {
* @Override
* public Optional<String> visitToken(Token token) {
* return Optional.of(token.toString());
* }
*
* // ...
*
* @Override
* public Optional<String> unknown(JsonValue json) {
* // Or inspect the `json`.
* return Optional.empty();
* }
* });
* ```
*
* @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and
* the current variant is unknown.
*/
fun <T> accept(visitor: Visitor<T>): T =
when {
token != null -> visitor.visitToken(token)
multipleTokens != null -> visitor.visitMultipleTokens(multipleTokens)
else -> visitor.unknown(_json)
}

private var validated: Boolean = false

/**
* Validates that the types of all values in this object match their expected types recursively.
*
* This method is _not_ forwards compatible with new types from the API for existing fields.
*
* @throws CourierInvalidDataException if any value type in this object doesn't match its
* expected type.
*/
fun validate(): Apn = apply {
if (validated) {
return@apply
}

accept(
object : Visitor<Unit> {
override fun visitToken(token: Token) {
token.validate()
}

override fun visitMultipleTokens(multipleTokens: MultipleTokens) {
multipleTokens.validate()
}
}
)
validated = true
}

fun isValid(): Boolean =
try {
validate()
true
} catch (e: CourierInvalidDataException) {
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<Int> {
override fun visitToken(token: Token) = token.validity()

override fun visitMultipleTokens(multipleTokens: MultipleTokens) =
multipleTokens.validity()

override fun unknown(json: JsonValue?) = 0
}
)

override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}

return other is Apn && token == other.token && multipleTokens == other.multipleTokens
}

override fun hashCode(): Int = Objects.hash(token, multipleTokens)

override fun toString(): String =
when {
token != null -> "Apn{token=$token}"
multipleTokens != null -> "Apn{multipleTokens=$multipleTokens}"
_json != null -> "Apn{_unknown=$_json}"
else -> throw IllegalStateException("Invalid Apn")
}

companion object {

@JvmStatic fun ofToken(token: Token) = Apn(token = token)

@JvmStatic
fun ofMultipleTokens(multipleTokens: MultipleTokens) = Apn(multipleTokens = multipleTokens)
}

/** An interface that defines how to map each variant of [Apn] to a value of type [T]. */
interface Visitor<out T> {

fun visitToken(token: Token): T

fun visitMultipleTokens(multipleTokens: MultipleTokens): T

/**
* Maps an unknown variant of [Apn] to a value of type [T].
*
* An instance of [Apn] 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 CourierInvalidDataException in the default implementation.
*/
fun unknown(json: JsonValue?): T {
throw CourierInvalidDataException("Unknown Apn: $json")
}
}

internal class Deserializer : BaseDeserializer<Apn>(Apn::class) {

override fun ObjectCodec.deserialize(node: JsonNode): Apn {
val json = JsonValue.fromJsonNode(node)

val bestMatches =
sequenceOf(
tryDeserialize(node, jacksonTypeRef<Token>())?.let {
Apn(token = it, _json = json)
},
tryDeserialize(node, jacksonTypeRef<MultipleTokens>())?.let {
Apn(multipleTokens = it, _json = json)
},
)
.filterNotNull()
.allMaxBy { it.validity() }
.toList()
return when (bestMatches.size) {
// This can happen if what we're deserializing is completely incompatible with all
// the possible variants (e.g. deserializing from boolean).
0 -> Apn(_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<Apn>(Apn::class) {

override fun serialize(value: Apn, generator: JsonGenerator, provider: SerializerProvider) {
when {
value.token != null -> generator.writeObject(value.token)
value.multipleTokens != null -> generator.writeObject(value.multipleTokens)
value._json != null -> generator.writeObject(value._json)
else -> throw IllegalStateException("Invalid Apn")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.fasterxml.jackson.module.kotlin.jacksonTypeRef
import java.util.Objects
import java.util.Optional

/** Expo push tokens. Supply either a single `token` or a `tokens` value. */
@JsonDeserialize(using = Expo.Deserializer::class)
@JsonSerialize(using = Expo.Serializer::class)
class Expo
Expand Down
Loading
Loading