diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 29102aeb..934f2cc0 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.3.0" + ".": "4.4.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index a8a912df..4b96b1ea 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 77 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-59c9efb45644c91ba21c8efaa0af53637071483ed661d5f99f27a15996624ac2.yml -openapi_spec_hash: 0e1d703ca5e68a4d1f1489c04eb43765 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-9859cb664d1a9de0323c857e96cf41d0a5ac5c5903c501059f36bf62553b1583.yml +openapi_spec_hash: d29149d60504eba35c63f583ce4bf0bc config_hash: 3ec521d062b05b81c22bc1a25bfe3d02 diff --git a/CHANGELOG.md b/CHANGELOG.md index 67bdf6c0..45abdcee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 4.4.0 (2025-12-16) + +Full Changelog: [v4.3.0...v4.4.0](https://github.com/trycourier/courier-java/compare/v4.3.0...v4.4.0) + +### Features + +* Add timezone field to Delay schema ([46d1671](https://github.com/trycourier/courier-java/commit/46d16713aeb86a15fe73de9c9e2aea168872a7c0)) +* Update bulk API spec: make event required, document profile.email req… ([e436dcd](https://github.com/trycourier/courier-java/commit/e436dcd0a916911f366d3016333b8a6a2cdc947d)) + ## 4.3.0 (2025-12-08) Full Changelog: [v4.2.0...v4.3.0](https://github.com/trycourier/courier-java/compare/v4.2.0...v4.3.0) diff --git a/README.md b/README.md index 295b49c3..8674e8ae 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.courier/courier-java)](https://central.sonatype.com/artifact/com.courier/courier-java/4.3.0) -[![javadoc](https://javadoc.io/badge2/com.courier/courier-java/4.3.0/javadoc.svg)](https://javadoc.io/doc/com.courier/courier-java/4.3.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.courier/courier-java)](https://central.sonatype.com/artifact/com.courier/courier-java/4.4.0) +[![javadoc](https://javadoc.io/badge2/com.courier/courier-java/4.4.0/javadoc.svg)](https://javadoc.io/doc/com.courier/courier-java/4.4.0) @@ -13,7 +13,7 @@ It is generated with [Stainless](https://www.stainless.com/). -The REST API documentation can be found on [www.courier.com](https://www.courier.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.courier/courier-java/4.3.0). +The REST API documentation can be found on [www.courier.com](https://www.courier.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.courier/courier-java/4.4.0). @@ -24,7 +24,7 @@ The REST API documentation can be found on [www.courier.com](https://www.courier ### Gradle ```kotlin -implementation("com.courier:courier-java:4.3.0") +implementation("com.courier:courier-java:4.4.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.courier:courier-java:4.3.0") com.courier courier-java - 4.3.0 + 4.4.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index ad02fa1b..63460547 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.courier" - version = "4.3.0" // x-release-please-version + version = "4.4.0" // x-release-please-version } subprojects { diff --git a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkAddUsersParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkAddUsersParams.kt index c192c3f9..9fc953d9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkAddUsersParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkAddUsersParams.kt @@ -22,7 +22,12 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Ingest user data into a Bulk Job */ +/** + * Ingest user data into a Bulk Job. + * + * **Important**: For email-based bulk jobs, each user must include `profile.email` for provider + * routing to work correctly. The `to.email` field is not sufficient for email provider routing. + */ class BulkAddUsersParams private constructor( private val jobId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobParams.kt index a96d04a1..573990e5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobParams.kt @@ -19,7 +19,14 @@ import java.util.Collections import java.util.Objects import kotlin.jvm.optionals.getOrNull -/** Create a bulk job */ +/** + * Creates a new bulk job for sending messages to multiple recipients. + * + * **Required**: `message.event` (event ID or notification ID) + * + * **Optional (V2 format)**: `message.template` (notification ID) or `message.content` (Elemental + * content) can be provided to override the notification associated with the event. + */ class BulkCreateJobParams private constructor( private val body: Body, @@ -28,6 +35,11 @@ private constructor( ) : Params { /** + * Bulk message definition. Supports two formats: + * - V1 format: Requires `event` field (event ID or notification ID) + * - V2 format: Optionally use `template` (notification ID) or `content` (Elemental content) in + * addition to `event` + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ @@ -86,6 +98,12 @@ private constructor( */ fun body(body: Body) = apply { this.body = body.toBuilder() } + /** + * Bulk message definition. Supports two formats: + * - V1 format: Requires `event` field (event ID or notification ID) + * - V2 format: Optionally use `template` (notification ID) or `content` (Elemental content) + * in addition to `event` + */ fun message(message: InboundBulkMessage) = apply { body.message(message) } /** @@ -97,16 +115,6 @@ private constructor( */ fun message(message: JsonField) = apply { body.message(message) } - /** Alias for calling [message] with `InboundBulkMessage.ofTemplate(template)`. */ - fun message(template: InboundBulkMessage.InboundBulkTemplateMessage) = apply { - body.message(template) - } - - /** Alias for calling [message] with `InboundBulkMessage.ofContent(content)`. */ - fun message(content: InboundBulkMessage.InboundBulkContentMessage) = apply { - body.message(content) - } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { body.additionalProperties(additionalBodyProperties) } @@ -265,6 +273,11 @@ private constructor( ) : this(message, mutableMapOf()) /** + * Bulk message definition. Supports two formats: + * - V1 format: Requires `event` field (event ID or notification ID) + * - V2 format: Optionally use `template` (notification ID) or `content` (Elemental content) + * in addition to `event` + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ @@ -316,6 +329,12 @@ private constructor( additionalProperties = body.additionalProperties.toMutableMap() } + /** + * Bulk message definition. Supports two formats: + * - V1 format: Requires `event` field (event ID or notification ID) + * - V2 format: Optionally use `template` (notification ID) or `content` (Elemental + * content) in addition to `event` + */ fun message(message: InboundBulkMessage) = message(JsonField.of(message)) /** @@ -327,14 +346,6 @@ private constructor( */ fun message(message: JsonField) = apply { this.message = message } - /** Alias for calling [message] with `InboundBulkMessage.ofTemplate(template)`. */ - fun message(template: InboundBulkMessage.InboundBulkTemplateMessage) = - message(InboundBulkMessage.ofTemplate(template)) - - /** Alias for calling [message] with `InboundBulkMessage.ofContent(content)`. */ - fun message(content: InboundBulkMessage.InboundBulkContentMessage) = - message(InboundBulkMessage.ofContent(content)) - fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) diff --git a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkListUsersResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkListUsersResponse.kt index e6da6e3d..d326f46d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkListUsersResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkListUsersResponse.kt @@ -211,7 +211,7 @@ private constructor( private constructor( private val data: JsonValue, private val preferences: JsonField, - private val profile: JsonValue, + private val profile: JsonField, private val recipient: JsonField, private val to: JsonField, private val status: JsonField, @@ -225,7 +225,9 @@ private constructor( @JsonProperty("preferences") @ExcludeMissing preferences: JsonField = JsonMissing.of(), - @JsonProperty("profile") @ExcludeMissing profile: JsonValue = JsonMissing.of(), + @JsonProperty("profile") + @ExcludeMissing + profile: JsonField = JsonMissing.of(), @JsonProperty("recipient") @ExcludeMissing recipient: JsonField = JsonMissing.of(), @@ -245,6 +247,7 @@ private constructor( .to(to) .build() + /** User-specific data that will be merged with message.data */ @JsonProperty("data") @ExcludeMissing fun _data(): JsonValue = data /** @@ -253,15 +256,29 @@ private constructor( */ fun preferences(): Optional = preferences.getOptional("preferences") - @JsonProperty("profile") @ExcludeMissing fun _profile(): JsonValue = profile + /** + * User profile information. For email-based bulk jobs, `profile.email` is required for + * provider routing to determine if the message can be delivered. The email address should + * be provided here rather than in `to.email`. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun profile(): Optional = profile.getOptional("profile") /** + * User ID (legacy field, use profile or to.user_id instead) + * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun recipient(): Optional = recipient.getOptional("recipient") /** + * Optional recipient information. Note: For email provider routing, use `profile.email` + * instead of `to.email`. The `to` field is primarily used for recipient identification and + * data merging. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -288,6 +305,15 @@ private constructor( @ExcludeMissing fun _preferences(): JsonField = preferences + /** + * Returns the raw JSON value of [profile]. + * + * Unlike [profile], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("profile") + @ExcludeMissing + fun _profile(): JsonField = profile + /** * Returns the raw JSON value of [recipient]. * @@ -346,7 +372,7 @@ private constructor( private var data: JsonValue = JsonMissing.of() private var preferences: JsonField = JsonMissing.of() - private var profile: JsonValue = JsonMissing.of() + private var profile: JsonField = JsonMissing.of() private var recipient: JsonField = JsonMissing.of() private var to: JsonField = JsonMissing.of() private var status: JsonField? = null @@ -365,6 +391,7 @@ private constructor( additionalProperties = item.additionalProperties.toMutableMap() } + /** User-specific data that will be merged with message.data */ fun data(data: JsonValue) = apply { this.data = data } fun preferences(preferences: RecipientPreferences?) = @@ -385,8 +412,30 @@ private constructor( this.preferences = preferences } - fun profile(profile: JsonValue) = apply { this.profile = profile } + /** + * User profile information. For email-based bulk jobs, `profile.email` is required for + * provider routing to determine if the message can be delivered. The email address + * should be provided here rather than in `to.email`. + */ + fun profile(profile: InboundBulkMessageUser.Profile?) = + profile(JsonField.ofNullable(profile)) + + /** Alias for calling [Builder.profile] with `profile.orElse(null)`. */ + fun profile(profile: Optional) = + profile(profile.getOrNull()) + /** + * Sets [Builder.profile] to an arbitrary JSON value. + * + * You should usually call [Builder.profile] with a well-typed + * [InboundBulkMessageUser.Profile] value instead. This method is primarily for setting + * the field to an undocumented or not yet supported value. + */ + fun profile(profile: JsonField) = apply { + this.profile = profile + } + + /** User ID (legacy field, use profile or to.user_id instead) */ fun recipient(recipient: String?) = recipient(JsonField.ofNullable(recipient)) /** Alias for calling [Builder.recipient] with `recipient.orElse(null)`. */ @@ -401,6 +450,11 @@ private constructor( */ fun recipient(recipient: JsonField) = apply { this.recipient = recipient } + /** + * Optional recipient information. Note: For email provider routing, use `profile.email` + * instead of `to.email`. The `to` field is primarily used for recipient identification + * and data merging. + */ fun to(to: UserRecipient?) = to(JsonField.ofNullable(to)) /** Alias for calling [Builder.to] with `to.orElse(null)`. */ @@ -492,6 +546,7 @@ private constructor( } preferences().ifPresent { it.validate() } + profile().ifPresent { it.validate() } recipient() to().ifPresent { it.validate() } status().validate() @@ -516,6 +571,7 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (preferences.asKnown().getOrNull()?.validity() ?: 0) + + (profile.asKnown().getOrNull()?.validity() ?: 0) + (if (recipient.asKnown().isPresent) 1 else 0) + (to.asKnown().getOrNull()?.validity() ?: 0) + (status.asKnown().getOrNull()?.validity() ?: 0) + diff --git a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkRetrieveJobResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkRetrieveJobResponse.kt index 04758a76..5dc1e0b1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkRetrieveJobResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkRetrieveJobResponse.kt @@ -173,6 +173,11 @@ private constructor( ) : this(definition, enqueued, failures, received, status, mutableMapOf()) /** + * Bulk message definition. Supports two formats: + * - V1 format: Requires `event` field (event ID or notification ID) + * - V2 format: Optionally use `template` (notification ID) or `content` (Elemental content) + * in addition to `event` + * * @throws CourierInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ @@ -288,6 +293,12 @@ private constructor( additionalProperties = job.additionalProperties.toMutableMap() } + /** + * Bulk message definition. Supports two formats: + * - V1 format: Requires `event` field (event ID or notification ID) + * - V2 format: Optionally use `template` (notification ID) or `content` (Elemental + * content) in addition to `event` + */ fun definition(definition: InboundBulkMessage) = definition(JsonField.of(definition)) /** @@ -301,14 +312,6 @@ private constructor( this.definition = definition } - /** Alias for calling [definition] with `InboundBulkMessage.ofTemplate(template)`. */ - fun definition(template: InboundBulkMessage.InboundBulkTemplateMessage) = - definition(InboundBulkMessage.ofTemplate(template)) - - /** Alias for calling [definition] with `InboundBulkMessage.ofContent(content)`. */ - fun definition(content: InboundBulkMessage.InboundBulkContentMessage) = - definition(InboundBulkMessage.ofContent(content)) - fun enqueued(enqueued: Long) = enqueued(JsonField.of(enqueued)) /** diff --git a/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessage.kt b/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessage.kt index 5f365b9c..9960181e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessage.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessage.kt @@ -31,414 +31,604 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -@JsonDeserialize(using = InboundBulkMessage.Deserializer::class) -@JsonSerialize(using = InboundBulkMessage.Serializer::class) +/** + * Bulk message definition. Supports two formats: + * - V1 format: Requires `event` field (event ID or notification ID) + * - V2 format: Optionally use `template` (notification ID) or `content` (Elemental content) in + * addition to `event` + */ class InboundBulkMessage +@JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val template: InboundBulkTemplateMessage? = null, - private val content: InboundBulkContentMessage? = null, - private val _json: JsonValue? = null, + private val event: JsonField, + private val brand: JsonField, + private val content: JsonField, + private val data: JsonField, + private val locale: JsonField, + private val override: JsonField, + private val template: JsonField, + private val additionalProperties: MutableMap, ) { - fun template(): Optional = Optional.ofNullable(template) - - fun content(): Optional = Optional.ofNullable(content) - - fun isTemplate(): Boolean = template != null + @JsonCreator + private constructor( + @JsonProperty("event") @ExcludeMissing event: JsonField = JsonMissing.of(), + @JsonProperty("brand") @ExcludeMissing brand: JsonField = JsonMissing.of(), + @JsonProperty("content") @ExcludeMissing content: JsonField = JsonMissing.of(), + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("locale") @ExcludeMissing locale: JsonField = JsonMissing.of(), + @JsonProperty("override") @ExcludeMissing override: JsonField = JsonMissing.of(), + @JsonProperty("template") @ExcludeMissing template: JsonField = JsonMissing.of(), + ) : this(event, brand, content, data, locale, override, template, mutableMapOf()) - fun isContent(): Boolean = content != null + /** + * Event ID or Notification ID (required). Can be either a Notification ID (e.g., + * "FRH3QXM9E34W4RKP7MRC8NZ1T8V8") or a custom Event ID (e.g., "welcome-email") mapped to a + * notification. + * + * @throws CourierInvalidDataException 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 event(): String = event.getRequired("event") - fun asTemplate(): InboundBulkTemplateMessage = template.getOrThrow("template") + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun brand(): Optional = brand.getOptional("brand") - fun asContent(): InboundBulkContentMessage = content.getOrThrow("content") + /** + * Elemental content (optional, for V2 format). When provided, this will be used instead of the + * notification associated with the `event` field. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun content(): Optional = content.getOptional("content") - fun _json(): Optional = Optional.ofNullable(_json) + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun data(): Optional = data.getOptional("data") - fun accept(visitor: Visitor): T = - when { - template != null -> visitor.visitTemplate(template) - content != null -> visitor.visitContent(content) - else -> visitor.unknown(_json) - } + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun locale(): Optional = locale.getOptional("locale") - private var validated: Boolean = false + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun override(): Optional = override.getOptional("override") - fun validate(): InboundBulkMessage = apply { - if (validated) { - return@apply - } + /** + * Notification ID or template ID (optional, for V2 format). When provided, this will be used + * instead of the notification associated with the `event` field. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun template(): Optional = template.getOptional("template") - accept( - object : Visitor { - override fun visitTemplate(template: InboundBulkTemplateMessage) { - template.validate() - } + /** + * Returns the raw JSON value of [event]. + * + * Unlike [event], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event - override fun visitContent(content: InboundBulkContentMessage) { - content.validate() - } - } - ) - validated = true - } + /** + * Returns the raw JSON value of [brand]. + * + * Unlike [brand], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("brand") @ExcludeMissing fun _brand(): JsonField = brand - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CourierInvalidDataException) { - false - } + /** + * Returns the raw JSON value of [content]. + * + * Unlike [content], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content /** - * Returns a score indicating how many valid values are contained in this object recursively. + * Returns the raw JSON value of [data]. * - * Used for best match union deserialization. + * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. */ - @JvmSynthetic - internal fun validity(): Int = - accept( - object : Visitor { - override fun visitTemplate(template: InboundBulkTemplateMessage) = - template.validity() + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - override fun visitContent(content: InboundBulkContentMessage) = content.validity() + /** + * Returns the raw JSON value of [locale]. + * + * Unlike [locale], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("locale") @ExcludeMissing fun _locale(): JsonField = locale - override fun unknown(json: JsonValue?) = 0 - } - ) + /** + * Returns the raw JSON value of [override]. + * + * Unlike [override], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("override") @ExcludeMissing fun _override(): JsonField = override - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** + * Returns the raw JSON value of [template]. + * + * Unlike [template], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("template") @ExcludeMissing fun _template(): JsonField = template - return other is InboundBulkMessage && template == other.template && content == other.content + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) } - override fun hashCode(): Int = Objects.hash(template, content) + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - override fun toString(): String = - when { - template != null -> "InboundBulkMessage{template=$template}" - content != null -> "InboundBulkMessage{content=$content}" - _json != null -> "InboundBulkMessage{_unknown=$_json}" - else -> throw IllegalStateException("Invalid InboundBulkMessage") - } + fun toBuilder() = Builder().from(this) companion object { - @JvmStatic - fun ofTemplate(template: InboundBulkTemplateMessage) = - InboundBulkMessage(template = template) - - @JvmStatic - fun ofContent(content: InboundBulkContentMessage) = InboundBulkMessage(content = content) - } - - /** - * An interface that defines how to map each variant of [InboundBulkMessage] to a value of type - * [T]. - */ - interface Visitor { - - fun visitTemplate(template: InboundBulkTemplateMessage): T - - fun visitContent(content: InboundBulkContentMessage): T - /** - * Maps an unknown variant of [InboundBulkMessage] to a value of type [T]. + * Returns a mutable builder for constructing an instance of [InboundBulkMessage]. * - * An instance of [InboundBulkMessage] 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. + * The following fields are required: + * ```java + * .event() + * ``` */ - fun unknown(json: JsonValue?): T { - throw CourierInvalidDataException("Unknown InboundBulkMessage: $json") - } + @JvmStatic fun builder() = Builder() } - internal class Deserializer : BaseDeserializer(InboundBulkMessage::class) { - - override fun ObjectCodec.deserialize(node: JsonNode): InboundBulkMessage { - val json = JsonValue.fromJsonNode(node) - - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - InboundBulkMessage(template = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - InboundBulkMessage(content = 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 -> InboundBulkMessage(_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() - } - } - } + /** A builder for [InboundBulkMessage]. */ + class Builder internal constructor() { - internal class Serializer : BaseSerializer(InboundBulkMessage::class) { + private var event: JsonField? = null + private var brand: JsonField = JsonMissing.of() + private var content: JsonField = JsonMissing.of() + private var data: JsonField = JsonMissing.of() + private var locale: JsonField = JsonMissing.of() + private var override: JsonField = JsonMissing.of() + private var template: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() - override fun serialize( - value: InboundBulkMessage, - generator: JsonGenerator, - provider: SerializerProvider, - ) { - when { - value.template != null -> generator.writeObject(value.template) - value.content != null -> generator.writeObject(value.content) - value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid InboundBulkMessage") - } + @JvmSynthetic + internal fun from(inboundBulkMessage: InboundBulkMessage) = apply { + event = inboundBulkMessage.event + brand = inboundBulkMessage.brand + content = inboundBulkMessage.content + data = inboundBulkMessage.data + locale = inboundBulkMessage.locale + override = inboundBulkMessage.override + template = inboundBulkMessage.template + additionalProperties = inboundBulkMessage.additionalProperties.toMutableMap() } - } - - class InboundBulkTemplateMessage - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val template: JsonField, - private val brand: JsonField, - private val data: JsonField, - private val event: JsonField, - private val locale: JsonField, - private val override: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("template") - @ExcludeMissing - template: JsonField = JsonMissing.of(), - @JsonProperty("brand") @ExcludeMissing brand: JsonField = JsonMissing.of(), - @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), - @JsonProperty("event") @ExcludeMissing event: JsonField = JsonMissing.of(), - @JsonProperty("locale") @ExcludeMissing locale: JsonField = JsonMissing.of(), - @JsonProperty("override") - @ExcludeMissing - override: JsonField = JsonMissing.of(), - ) : this(template, brand, data, event, locale, override, mutableMapOf()) /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + * Event ID or Notification ID (required). Can be either a Notification ID (e.g., + * "FRH3QXM9E34W4RKP7MRC8NZ1T8V8") or a custom Event ID (e.g., "welcome-email") mapped to a + * notification. */ - fun template(): String = template.getRequired("template") + fun event(event: String) = event(JsonField.of(event)) /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * Sets [Builder.event] to an arbitrary JSON value. + * + * You should usually call [Builder.event] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun brand(): Optional = brand.getOptional("brand") + fun event(event: JsonField) = apply { this.event = event } + + fun brand(brand: String?) = brand(JsonField.ofNullable(brand)) + + /** Alias for calling [Builder.brand] with `brand.orElse(null)`. */ + fun brand(brand: Optional) = brand(brand.getOrNull()) /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * Sets [Builder.brand] to an arbitrary JSON value. + * + * You should usually call [Builder.brand] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun data(): Optional = data.getOptional("data") + fun brand(brand: JsonField) = apply { this.brand = brand } /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * Elemental content (optional, for V2 format). When provided, this will be used instead of + * the notification associated with the `event` field. */ - fun event(): Optional = event.getOptional("event") + fun content(content: Content?) = content(JsonField.ofNullable(content)) + + /** Alias for calling [Builder.content] with `content.orElse(null)`. */ + fun content(content: Optional) = content(content.getOrNull()) /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * Sets [Builder.content] to an arbitrary JSON value. + * + * You should usually call [Builder.content] with a well-typed [Content] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun locale(): Optional = locale.getOptional("locale") + fun content(content: JsonField) = apply { this.content = content } /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). + * Alias for calling [content] with + * `Content.ofElementalContentSugar(elementalContentSugar)`. */ - fun override(): Optional = override.getOptional("override") + fun content(elementalContentSugar: ElementalContentSugar) = + content(Content.ofElementalContentSugar(elementalContentSugar)) + + /** Alias for calling [content] with `Content.ofElemental(elemental)`. */ + fun content(elemental: ElementalContent) = content(Content.ofElemental(elemental)) + + fun data(data: Data?) = data(JsonField.ofNullable(data)) + + /** Alias for calling [Builder.data] with `data.orElse(null)`. */ + fun data(data: Optional) = data(data.getOrNull()) /** - * Returns the raw JSON value of [template]. + * Sets [Builder.data] to an arbitrary JSON value. * - * Unlike [template], this method doesn't throw if the JSON field has an unexpected type. + * You should usually call [Builder.data] with a well-typed [Data] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - @JsonProperty("template") @ExcludeMissing fun _template(): JsonField = template + fun data(data: JsonField) = apply { this.data = data } + + fun locale(locale: Locale?) = locale(JsonField.ofNullable(locale)) + + /** Alias for calling [Builder.locale] with `locale.orElse(null)`. */ + fun locale(locale: Optional) = locale(locale.getOrNull()) /** - * Returns the raw JSON value of [brand]. + * Sets [Builder.locale] to an arbitrary JSON value. * - * Unlike [brand], this method doesn't throw if the JSON field has an unexpected type. + * You should usually call [Builder.locale] with a well-typed [Locale] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - @JsonProperty("brand") @ExcludeMissing fun _brand(): JsonField = brand + fun locale(locale: JsonField) = apply { this.locale = locale } + + fun override(override: Override?) = override(JsonField.ofNullable(override)) + + /** Alias for calling [Builder.override] with `override.orElse(null)`. */ + fun override(override: Optional) = override(override.getOrNull()) /** - * Returns the raw JSON value of [data]. + * Sets [Builder.override] to an arbitrary JSON value. * - * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. + * You should usually call [Builder.override] with a well-typed [Override] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. */ - @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data + fun override(override: JsonField) = apply { this.override = override } /** - * Returns the raw JSON value of [event]. - * - * Unlike [event], this method doesn't throw if the JSON field has an unexpected type. + * Notification ID or template ID (optional, for V2 format). When provided, this will be + * used instead of the notification associated with the `event` field. */ - @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event + fun template(template: String?) = template(JsonField.ofNullable(template)) + + /** Alias for calling [Builder.template] with `template.orElse(null)`. */ + fun template(template: Optional) = template(template.getOrNull()) /** - * Returns the raw JSON value of [locale]. + * Sets [Builder.template] to an arbitrary JSON value. * - * Unlike [locale], this method doesn't throw if the JSON field has an unexpected type. + * You should usually call [Builder.template] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - @JsonProperty("locale") @ExcludeMissing fun _locale(): JsonField = locale + fun template(template: JsonField) = apply { this.template = template } + + 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 the raw JSON value of [override]. + * Returns an immutable instance of [InboundBulkMessage]. * - * Unlike [override], this method doesn't throw if the JSON field has an unexpected type. + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .event() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ - @JsonProperty("override") @ExcludeMissing fun _override(): JsonField = override + fun build(): InboundBulkMessage = + InboundBulkMessage( + checkRequired("event", event), + brand, + content, + data, + locale, + override, + template, + additionalProperties.toMutableMap(), + ) + } - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) + private var validated: Boolean = false + + fun validate(): InboundBulkMessage = apply { + if (validated) { + return@apply } - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + event() + brand() + content().ifPresent { it.validate() } + data().ifPresent { it.validate() } + locale().ifPresent { it.validate() } + override().ifPresent { it.validate() } + template() + validated = true + } - fun toBuilder() = Builder().from(this) + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } - companion object { + /** + * Returns 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 (event.asKnown().isPresent) 1 else 0) + + (if (brand.asKnown().isPresent) 1 else 0) + + (content.asKnown().getOrNull()?.validity() ?: 0) + + (data.asKnown().getOrNull()?.validity() ?: 0) + + (locale.asKnown().getOrNull()?.validity() ?: 0) + + (override.asKnown().getOrNull()?.validity() ?: 0) + + (if (template.asKnown().isPresent) 1 else 0) - /** - * Returns a mutable builder for constructing an instance of - * [InboundBulkTemplateMessage]. - * - * The following fields are required: - * ```java - * .template() - * ``` - */ - @JvmStatic fun builder() = Builder() + /** + * Elemental content (optional, for V2 format). When provided, this will be used instead of the + * notification associated with the `event` field. + */ + @JsonDeserialize(using = Content.Deserializer::class) + @JsonSerialize(using = Content.Serializer::class) + class Content + private constructor( + private val elementalContentSugar: ElementalContentSugar? = null, + private val elemental: ElementalContent? = null, + private val _json: JsonValue? = null, + ) { + + /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ + fun elementalContentSugar(): Optional = + Optional.ofNullable(elementalContentSugar) + + fun elemental(): Optional = Optional.ofNullable(elemental) + + fun isElementalContentSugar(): Boolean = elementalContentSugar != null + + fun isElemental(): Boolean = elemental != null + + /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ + fun asElementalContentSugar(): ElementalContentSugar = + elementalContentSugar.getOrThrow("elementalContentSugar") + + fun asElemental(): ElementalContent = elemental.getOrThrow("elemental") + + fun _json(): Optional = Optional.ofNullable(_json) + + fun accept(visitor: Visitor): T = + when { + elementalContentSugar != null -> + visitor.visitElementalContentSugar(elementalContentSugar) + elemental != null -> visitor.visitElemental(elemental) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + fun validate(): Content = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitElementalContentSugar( + elementalContentSugar: ElementalContentSugar + ) { + elementalContentSugar.validate() + } + + override fun visitElemental(elemental: ElementalContent) { + elemental.validate() + } + } + ) + validated = true } - /** A builder for [InboundBulkTemplateMessage]. */ - class Builder internal constructor() { + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false + } - private var template: JsonField? = null - private var brand: JsonField = JsonMissing.of() - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() - private var locale: JsonField = JsonMissing.of() - private var override: JsonField = JsonMissing.of() - private var additionalProperties: MutableMap = mutableMapOf() + /** + * Returns 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 visitElementalContentSugar( + elementalContentSugar: ElementalContentSugar + ) = elementalContentSugar.validity() - @JvmSynthetic - internal fun from(inboundBulkTemplateMessage: InboundBulkTemplateMessage) = apply { - template = inboundBulkTemplateMessage.template - brand = inboundBulkTemplateMessage.brand - data = inboundBulkTemplateMessage.data - event = inboundBulkTemplateMessage.event - locale = inboundBulkTemplateMessage.locale - override = inboundBulkTemplateMessage.override - additionalProperties = - inboundBulkTemplateMessage.additionalProperties.toMutableMap() + override fun visitElemental(elemental: ElementalContent) = elemental.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true } - fun template(template: String) = template(JsonField.of(template)) + return other is Content && + elementalContentSugar == other.elementalContentSugar && + elemental == other.elemental + } - /** - * Sets [Builder.template] to an arbitrary JSON value. - * - * You should usually call [Builder.template] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun template(template: JsonField) = apply { this.template = template } + override fun hashCode(): Int = Objects.hash(elementalContentSugar, elemental) - fun brand(brand: String?) = brand(JsonField.ofNullable(brand)) + override fun toString(): String = + when { + elementalContentSugar != null -> + "Content{elementalContentSugar=$elementalContentSugar}" + elemental != null -> "Content{elemental=$elemental}" + _json != null -> "Content{_unknown=$_json}" + else -> throw IllegalStateException("Invalid Content") + } - /** Alias for calling [Builder.brand] with `brand.orElse(null)`. */ - fun brand(brand: Optional) = brand(brand.getOrNull()) + companion object { - /** - * Sets [Builder.brand] to an arbitrary JSON value. - * - * You should usually call [Builder.brand] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun brand(brand: JsonField) = apply { this.brand = brand } + /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ + @JvmStatic + fun ofElementalContentSugar(elementalContentSugar: ElementalContentSugar) = + Content(elementalContentSugar = elementalContentSugar) + + @JvmStatic fun ofElemental(elemental: ElementalContent) = Content(elemental = elemental) + } + + /** + * An interface that defines how to map each variant of [Content] to a value of type [T]. + */ + interface Visitor { - fun data(data: Data?) = data(JsonField.ofNullable(data)) + /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ + fun visitElementalContentSugar(elementalContentSugar: ElementalContentSugar): T - /** Alias for calling [Builder.data] with `data.orElse(null)`. */ - fun data(data: Optional) = data(data.getOrNull()) + fun visitElemental(elemental: ElementalContent): T /** - * Sets [Builder.data] to an arbitrary JSON value. + * Maps an unknown variant of [Content] to a value of type [T]. + * + * An instance of [Content] 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. * - * You should usually call [Builder.data] with a well-typed [Data] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. + * @throws CourierInvalidDataException in the default implementation. */ - fun data(data: JsonField) = apply { this.data = data } + fun unknown(json: JsonValue?): T { + throw CourierInvalidDataException("Unknown Content: $json") + } + } - fun event(event: String?) = event(JsonField.ofNullable(event)) + internal class Deserializer : BaseDeserializer(Content::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): Content { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + Content(elementalContentSugar = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + Content(elemental = 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 -> Content(_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() + } + } + } - /** Alias for calling [Builder.event] with `event.orElse(null)`. */ - fun event(event: Optional) = event(event.getOrNull()) + internal class Serializer : BaseSerializer(Content::class) { - /** - * Sets [Builder.event] to an arbitrary JSON value. - * - * You should usually call [Builder.event] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun event(event: JsonField) = apply { this.event = event } + override fun serialize( + value: Content, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.elementalContentSugar != null -> + generator.writeObject(value.elementalContentSugar) + value.elemental != null -> generator.writeObject(value.elemental) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid Content") + } + } + } + } + + class Data + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { - fun locale(locale: Locale?) = locale(JsonField.ofNullable(locale)) + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties - /** Alias for calling [Builder.locale] with `locale.orElse(null)`. */ - fun locale(locale: Optional) = locale(locale.getOrNull()) + fun toBuilder() = Builder().from(this) - /** - * Sets [Builder.locale] to an arbitrary JSON value. - * - * You should usually call [Builder.locale] with a well-typed [Locale] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun locale(locale: JsonField) = apply { this.locale = locale } + companion object { - fun override(override: Override?) = override(JsonField.ofNullable(override)) + /** Returns a mutable builder for constructing an instance of [Data]. */ + @JvmStatic fun builder() = Builder() + } - /** Alias for calling [Builder.override] with `override.orElse(null)`. */ - fun override(override: Optional) = override(override.getOrNull()) + /** A builder for [Data]. */ + class Builder internal constructor() { - /** - * Sets [Builder.override] to an arbitrary JSON value. - * - * You should usually call [Builder.override] with a well-typed [Override] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun override(override: JsonField) = apply { this.override = override } + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(data: Data) = apply { + additionalProperties = data.additionalProperties.toMutableMap() + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -460,42 +650,20 @@ private constructor( } /** - * Returns an immutable instance of [InboundBulkTemplateMessage]. + * Returns an immutable instance of [Data]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .template() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ - fun build(): InboundBulkTemplateMessage = - InboundBulkTemplateMessage( - checkRequired("template", template), - brand, - data, - event, - locale, - override, - additionalProperties.toMutableMap(), - ) + fun build(): Data = Data(additionalProperties.toImmutable()) } private var validated: Boolean = false - fun validate(): InboundBulkTemplateMessage = apply { + fun validate(): Data = apply { if (validated) { return@apply } - template() - brand() - data().ifPresent { it.validate() } - event() - locale().ifPresent { it.validate() } - override().ifPresent { it.validate() } validated = true } @@ -515,588 +683,151 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (template.asKnown().isPresent) 1 else 0) + - (if (brand.asKnown().isPresent) 1 else 0) + - (data.asKnown().getOrNull()?.validity() ?: 0) + - (if (event.asKnown().isPresent) 1 else 0) + - (locale.asKnown().getOrNull()?.validity() ?: 0) + - (override.asKnown().getOrNull()?.validity() ?: 0) - - class Data - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Data]. */ - @JvmStatic fun builder() = Builder() + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true } - /** A builder for [Data]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() + return other is Data && additionalProperties == other.additionalProperties + } - @JvmSynthetic - internal fun from(data: Data) = apply { - additionalProperties = data.additionalProperties.toMutableMap() - } + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } - - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + override fun hashCode(): Int = hashCode - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) - } + override fun toString() = "Data{additionalProperties=$additionalProperties}" + } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + class Locale + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties - /** - * Returns an immutable instance of [Data]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Data = Data(additionalProperties.toImmutable()) - } + fun toBuilder() = Builder().from(this) - private var validated: Boolean = false + companion object { - fun validate(): Data = apply { - if (validated) { - return@apply - } + /** Returns a mutable builder for constructing an instance of [Locale]. */ + @JvmStatic fun builder() = Builder() + } - validated = true - } + /** A builder for [Locale]. */ + class Builder internal constructor() { - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CourierInvalidDataException) { - false - } + private var additionalProperties: MutableMap = mutableMapOf() - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ @JvmSynthetic - internal fun validity(): Int = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Data && additionalProperties == other.additionalProperties + internal fun from(locale: Locale) = apply { + additionalProperties = locale.additionalProperties.toMutableMap() } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Data{additionalProperties=$additionalProperties}" - } - - class Locale - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Locale]. */ - @JvmStatic fun builder() = Builder() + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) } - /** A builder for [Locale]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(locale: Locale) = apply { - additionalProperties = locale.additionalProperties.toMutableMap() - } - - 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 [Locale]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Locale = Locale(additionalProperties.toImmutable()) + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) } - private var validated: Boolean = false + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } - fun validate(): Locale = apply { - if (validated) { - return@apply - } + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } - validated = true + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: CourierInvalidDataException) { - false - } - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. + * Returns an immutable instance of [Locale]. * - * Used for best match union deserialization. + * Further updates to this [Builder] will not mutate the returned instance. */ - @JvmSynthetic - internal fun validity(): Int = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Locale && additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Locale{additionalProperties=$additionalProperties}" + fun build(): Locale = Locale(additionalProperties.toImmutable()) } - class Override - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Override]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Override]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(override: Override) = apply { - additionalProperties = override.additionalProperties.toMutableMap() - } - - 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 [Override]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Override = Override(additionalProperties.toImmutable()) - } - - private var validated: Boolean = false - - fun validate(): Override = apply { - if (validated) { - return@apply - } + private var validated: Boolean = false - validated = true + fun validate(): Locale = apply { + if (validated) { + return@apply } - 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 = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + validated = true + } - return other is Override && additionalProperties == other.additionalProperties + fun isValid(): Boolean = + try { + validate() + true + } catch (e: CourierInvalidDataException) { + false } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Override{additionalProperties=$additionalProperties}" - } + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } override fun equals(other: Any?): Boolean { if (this === other) { return true } - return other is InboundBulkTemplateMessage && - template == other.template && - brand == other.brand && - data == other.data && - event == other.event && - locale == other.locale && - override == other.override && - additionalProperties == other.additionalProperties + return other is Locale && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { - Objects.hash(template, brand, data, event, locale, override, additionalProperties) - } + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = - "InboundBulkTemplateMessage{template=$template, brand=$brand, data=$data, event=$event, locale=$locale, override=$override, additionalProperties=$additionalProperties}" + override fun toString() = "Locale{additionalProperties=$additionalProperties}" } - class InboundBulkContentMessage - @JsonCreator(mode = JsonCreator.Mode.DISABLED) + class Override + @JsonCreator private constructor( - private val content: JsonField, - private val brand: JsonField, - private val data: JsonField, - private val event: JsonField, - private val locale: JsonField, - private val override: JsonField, - private val additionalProperties: MutableMap, + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map ) { - @JsonCreator - private constructor( - @JsonProperty("content") @ExcludeMissing content: JsonField = JsonMissing.of(), - @JsonProperty("brand") @ExcludeMissing brand: JsonField = JsonMissing.of(), - @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), - @JsonProperty("event") @ExcludeMissing event: JsonField = JsonMissing.of(), - @JsonProperty("locale") @ExcludeMissing locale: JsonField = JsonMissing.of(), - @JsonProperty("override") - @ExcludeMissing - override: JsonField = JsonMissing.of(), - ) : this(content, brand, data, event, locale, override, mutableMapOf()) - - /** - * Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. - * - * @throws CourierInvalidDataException 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 content(): Content = content.getRequired("content") - - /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun brand(): Optional = brand.getOptional("brand") - - /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun data(): Optional = data.getOptional("data") - - /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun event(): Optional = event.getOptional("event") - - /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun locale(): Optional = locale.getOptional("locale") - - /** - * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the - * server responded with an unexpected value). - */ - fun override(): Optional = override.getOptional("override") - - /** - * Returns the raw JSON value of [content]. - * - * Unlike [content], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content - - /** - * Returns the raw JSON value of [brand]. - * - * Unlike [brand], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("brand") @ExcludeMissing fun _brand(): JsonField = brand - - /** - * Returns the raw JSON value of [data]. - * - * Unlike [data], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - - /** - * Returns the raw JSON value of [event]. - * - * Unlike [event], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event - - /** - * Returns the raw JSON value of [locale]. - * - * Unlike [locale], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("locale") @ExcludeMissing fun _locale(): JsonField = locale - - /** - * Returns the raw JSON value of [override]. - * - * Unlike [override], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("override") @ExcludeMissing fun _override(): JsonField = override - - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } - @JsonAnyGetter @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + fun _additionalProperties(): Map = additionalProperties fun toBuilder() = Builder().from(this) companion object { - /** - * Returns a mutable builder for constructing an instance of - * [InboundBulkContentMessage]. - * - * The following fields are required: - * ```java - * .content() - * ``` - */ + /** Returns a mutable builder for constructing an instance of [Override]. */ @JvmStatic fun builder() = Builder() } - /** A builder for [InboundBulkContentMessage]. */ + /** A builder for [Override]. */ class Builder internal constructor() { - private var content: JsonField? = null - private var brand: JsonField = JsonMissing.of() - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() - private var locale: JsonField = JsonMissing.of() - private var override: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(inboundBulkContentMessage: InboundBulkContentMessage) = apply { - content = inboundBulkContentMessage.content - brand = inboundBulkContentMessage.brand - data = inboundBulkContentMessage.data - event = inboundBulkContentMessage.event - locale = inboundBulkContentMessage.locale - override = inboundBulkContentMessage.override - additionalProperties = inboundBulkContentMessage.additionalProperties.toMutableMap() + internal fun from(override: Override) = apply { + additionalProperties = override.additionalProperties.toMutableMap() } - /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ - fun content(content: Content) = content(JsonField.of(content)) - - /** - * Sets [Builder.content] to an arbitrary JSON value. - * - * You should usually call [Builder.content] with a well-typed [Content] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun content(content: JsonField) = apply { this.content = content } - - /** - * Alias for calling [content] with - * `Content.ofElementalContentSugar(elementalContentSugar)`. - */ - fun content(elementalContentSugar: ElementalContentSugar) = - content(Content.ofElementalContentSugar(elementalContentSugar)) - - /** Alias for calling [content] with `Content.ofElemental(elemental)`. */ - fun content(elemental: ElementalContent) = content(Content.ofElemental(elemental)) - - fun brand(brand: String?) = brand(JsonField.ofNullable(brand)) - - /** Alias for calling [Builder.brand] with `brand.orElse(null)`. */ - fun brand(brand: Optional) = brand(brand.getOrNull()) - - /** - * Sets [Builder.brand] to an arbitrary JSON value. - * - * You should usually call [Builder.brand] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun brand(brand: JsonField) = apply { this.brand = brand } - - fun data(data: Data?) = data(JsonField.ofNullable(data)) - - /** Alias for calling [Builder.data] with `data.orElse(null)`. */ - fun data(data: Optional) = data(data.getOrNull()) - - /** - * Sets [Builder.data] to an arbitrary JSON value. - * - * You should usually call [Builder.data] with a well-typed [Data] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun data(data: JsonField) = apply { this.data = data } - - fun event(event: String?) = event(JsonField.ofNullable(event)) - - /** Alias for calling [Builder.event] with `event.orElse(null)`. */ - fun event(event: Optional) = event(event.getOrNull()) - - /** - * Sets [Builder.event] to an arbitrary JSON value. - * - * You should usually call [Builder.event] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun event(event: JsonField) = apply { this.event = event } - - fun locale(locale: Locale?) = locale(JsonField.ofNullable(locale)) - - /** Alias for calling [Builder.locale] with `locale.orElse(null)`. */ - fun locale(locale: Optional) = locale(locale.getOrNull()) - - /** - * Sets [Builder.locale] to an arbitrary JSON value. - * - * You should usually call [Builder.locale] with a well-typed [Locale] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun locale(locale: JsonField) = apply { this.locale = locale } - - fun override(override: Override?) = override(JsonField.ofNullable(override)) - - /** Alias for calling [Builder.override] with `override.orElse(null)`. */ - fun override(override: Optional) = override(override.getOrNull()) - - /** - * Sets [Builder.override] to an arbitrary JSON value. - * - * You should usually call [Builder.override] with a well-typed [Override] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun override(override: JsonField) = apply { this.override = override } - fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -1117,42 +848,20 @@ private constructor( } /** - * Returns an immutable instance of [InboundBulkContentMessage]. + * Returns an immutable instance of [Override]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .content() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ - fun build(): InboundBulkContentMessage = - InboundBulkContentMessage( - checkRequired("content", content), - brand, - data, - event, - locale, - override, - additionalProperties.toMutableMap(), - ) + fun build(): Override = Override(additionalProperties.toImmutable()) } private var validated: Boolean = false - fun validate(): InboundBulkContentMessage = apply { + fun validate(): Override = apply { if (validated) { return@apply } - content().validate() - brand() - data().ifPresent { it.validate() } - event() - locale().ifPresent { it.validate() } - override().ifPresent { it.validate() } validated = true } @@ -1172,535 +881,45 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (content.asKnown().getOrNull()?.validity() ?: 0) + - (if (brand.asKnown().isPresent) 1 else 0) + - (data.asKnown().getOrNull()?.validity() ?: 0) + - (if (event.asKnown().isPresent) 1 else 0) + - (locale.asKnown().getOrNull()?.validity() ?: 0) + - (override.asKnown().getOrNull()?.validity() ?: 0) - - /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ - @JsonDeserialize(using = Content.Deserializer::class) - @JsonSerialize(using = Content.Serializer::class) - class Content - private constructor( - private val elementalContentSugar: ElementalContentSugar? = null, - private val elemental: ElementalContent? = null, - private val _json: JsonValue? = null, - ) { - - /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ - fun elementalContentSugar(): Optional = - Optional.ofNullable(elementalContentSugar) - - fun elemental(): Optional = Optional.ofNullable(elemental) - - fun isElementalContentSugar(): Boolean = elementalContentSugar != null - - fun isElemental(): Boolean = elemental != null - - /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ - fun asElementalContentSugar(): ElementalContentSugar = - elementalContentSugar.getOrThrow("elementalContentSugar") - - fun asElemental(): ElementalContent = elemental.getOrThrow("elemental") - - fun _json(): Optional = Optional.ofNullable(_json) - - fun accept(visitor: Visitor): T = - when { - elementalContentSugar != null -> - visitor.visitElementalContentSugar(elementalContentSugar) - elemental != null -> visitor.visitElemental(elemental) - else -> visitor.unknown(_json) - } - - private var validated: Boolean = false - - fun validate(): Content = apply { - if (validated) { - return@apply - } - - accept( - object : Visitor { - override fun visitElementalContentSugar( - elementalContentSugar: ElementalContentSugar - ) { - elementalContentSugar.validate() - } - - override fun visitElemental(elemental: ElementalContent) { - elemental.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 { - override fun visitElementalContentSugar( - elementalContentSugar: ElementalContentSugar - ) = elementalContentSugar.validity() - - override fun visitElemental(elemental: ElementalContent) = - elemental.validity() - - override fun unknown(json: JsonValue?) = 0 - } - ) - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Content && - elementalContentSugar == other.elementalContentSugar && - elemental == other.elemental - } - - override fun hashCode(): Int = Objects.hash(elementalContentSugar, elemental) - - override fun toString(): String = - when { - elementalContentSugar != null -> - "Content{elementalContentSugar=$elementalContentSugar}" - elemental != null -> "Content{elemental=$elemental}" - _json != null -> "Content{_unknown=$_json}" - else -> throw IllegalStateException("Invalid Content") - } - - companion object { - - /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ - @JvmStatic - fun ofElementalContentSugar(elementalContentSugar: ElementalContentSugar) = - Content(elementalContentSugar = elementalContentSugar) - - @JvmStatic - fun ofElemental(elemental: ElementalContent) = Content(elemental = elemental) - } - - /** - * An interface that defines how to map each variant of [Content] to a value of type - * [T]. - */ - interface Visitor { - - /** Syntactic sugar to provide a fast shorthand for Courier Elemental Blocks. */ - fun visitElementalContentSugar(elementalContentSugar: ElementalContentSugar): T - - fun visitElemental(elemental: ElementalContent): T - - /** - * Maps an unknown variant of [Content] to a value of type [T]. - * - * An instance of [Content] 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 Content: $json") - } - } - - internal class Deserializer : BaseDeserializer(Content::class) { - - override fun ObjectCodec.deserialize(node: JsonNode): Content { - val json = JsonValue.fromJsonNode(node) - - val bestMatches = - sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Content(elementalContentSugar = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - Content(elemental = 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 -> Content(_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(Content::class) { - - override fun serialize( - value: Content, - generator: JsonGenerator, - provider: SerializerProvider, - ) { - when { - value.elementalContentSugar != null -> - generator.writeObject(value.elementalContentSugar) - value.elemental != null -> generator.writeObject(value.elemental) - value._json != null -> generator.writeObject(value._json) - else -> throw IllegalStateException("Invalid Content") - } - } - } - } - - class Data - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Data]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Data]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(data: Data) = apply { - additionalProperties = data.additionalProperties.toMutableMap() - } - - 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 [Data]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Data = Data(additionalProperties.toImmutable()) - } - - private var validated: Boolean = false - - fun validate(): Data = apply { - if (validated) { - return@apply - } - - 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 = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Data && additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Data{additionalProperties=$additionalProperties}" - } - - class Locale - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Locale]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Locale]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(locale: Locale) = apply { - additionalProperties = locale.additionalProperties.toMutableMap() - } - - 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) - } + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } - - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } - - /** - * Returns an immutable instance of [Locale]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Locale = Locale(additionalProperties.toImmutable()) - } - - private var validated: Boolean = false - - fun validate(): Locale = apply { - if (validated) { - return@apply - } - - 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 = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Locale && additionalProperties == other.additionalProperties + override fun equals(other: Any?): Boolean { + if (this === other) { + return true } - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - - override fun hashCode(): Int = hashCode - - override fun toString() = "Locale{additionalProperties=$additionalProperties}" + return other is Override && additionalProperties == other.additionalProperties } - class Override - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Override]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Override]. */ - class Builder internal constructor() { - - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(override: Override) = apply { - additionalProperties = override.additionalProperties.toMutableMap() - } - - 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 [Override]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Override = Override(additionalProperties.toImmutable()) - } - - private var validated: Boolean = false - - fun validate(): Override = apply { - if (validated) { - return@apply - } - - 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 = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } - - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is Override && additionalProperties == other.additionalProperties - } - - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + override fun hashCode(): Int = hashCode - override fun hashCode(): Int = hashCode + override fun toString() = "Override{additionalProperties=$additionalProperties}" + } - override fun toString() = "Override{additionalProperties=$additionalProperties}" + override fun equals(other: Any?): Boolean { + if (this === other) { + return true } - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - - return other is InboundBulkContentMessage && - content == other.content && - brand == other.brand && - data == other.data && - event == other.event && - locale == other.locale && - override == other.override && - additionalProperties == other.additionalProperties - } + return other is InboundBulkMessage && + event == other.event && + brand == other.brand && + content == other.content && + data == other.data && + locale == other.locale && + override == other.override && + template == other.template && + additionalProperties == other.additionalProperties + } - private val hashCode: Int by lazy { - Objects.hash(content, brand, data, event, locale, override, additionalProperties) - } + private val hashCode: Int by lazy { + Objects.hash(event, brand, content, data, locale, override, template, additionalProperties) + } - override fun hashCode(): Int = hashCode + override fun hashCode(): Int = hashCode - override fun toString() = - "InboundBulkContentMessage{content=$content, brand=$brand, data=$data, event=$event, locale=$locale, override=$override, additionalProperties=$additionalProperties}" - } + override fun toString() = + "InboundBulkMessage{event=$event, brand=$brand, content=$content, data=$data, locale=$locale, override=$override, template=$template, additionalProperties=$additionalProperties}" } diff --git a/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessageUser.kt b/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessageUser.kt index e7ceb8df..4c058b4c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessageUser.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/bulk/InboundBulkMessageUser.kt @@ -6,6 +6,7 @@ import com.courier.core.ExcludeMissing import com.courier.core.JsonField import com.courier.core.JsonMissing import com.courier.core.JsonValue +import com.courier.core.toImmutable import com.courier.errors.CourierInvalidDataException import com.courier.models.RecipientPreferences import com.courier.models.UserRecipient @@ -23,7 +24,7 @@ class InboundBulkMessageUser private constructor( private val data: JsonValue, private val preferences: JsonField, - private val profile: JsonValue, + private val profile: JsonField, private val recipient: JsonField, private val to: JsonField, private val additionalProperties: MutableMap, @@ -35,11 +36,12 @@ private constructor( @JsonProperty("preferences") @ExcludeMissing preferences: JsonField = JsonMissing.of(), - @JsonProperty("profile") @ExcludeMissing profile: JsonValue = JsonMissing.of(), + @JsonProperty("profile") @ExcludeMissing profile: JsonField = JsonMissing.of(), @JsonProperty("recipient") @ExcludeMissing recipient: JsonField = JsonMissing.of(), @JsonProperty("to") @ExcludeMissing to: JsonField = JsonMissing.of(), ) : this(data, preferences, profile, recipient, to, mutableMapOf()) + /** User-specific data that will be merged with message.data */ @JsonProperty("data") @ExcludeMissing fun _data(): JsonValue = data /** @@ -48,15 +50,29 @@ private constructor( */ fun preferences(): Optional = preferences.getOptional("preferences") - @JsonProperty("profile") @ExcludeMissing fun _profile(): JsonValue = profile + /** + * User profile information. For email-based bulk jobs, `profile.email` is required for provider + * routing to determine if the message can be delivered. The email address should be provided + * here rather than in `to.email`. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun profile(): Optional = profile.getOptional("profile") /** + * User ID (legacy field, use profile or to.user_id instead) + * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ fun recipient(): Optional = recipient.getOptional("recipient") /** + * Optional recipient information. Note: For email provider routing, use `profile.email` instead + * of `to.email`. The `to` field is primarily used for recipient identification and data + * merging. + * * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). */ @@ -71,6 +87,13 @@ private constructor( @ExcludeMissing fun _preferences(): JsonField = preferences + /** + * Returns the raw JSON value of [profile]. + * + * Unlike [profile], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("profile") @ExcludeMissing fun _profile(): JsonField = profile + /** * Returns the raw JSON value of [recipient]. * @@ -108,7 +131,7 @@ private constructor( private var data: JsonValue = JsonMissing.of() private var preferences: JsonField = JsonMissing.of() - private var profile: JsonValue = JsonMissing.of() + private var profile: JsonField = JsonMissing.of() private var recipient: JsonField = JsonMissing.of() private var to: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -123,6 +146,7 @@ private constructor( additionalProperties = inboundBulkMessageUser.additionalProperties.toMutableMap() } + /** User-specific data that will be merged with message.data */ fun data(data: JsonValue) = apply { this.data = data } fun preferences(preferences: RecipientPreferences?) = @@ -143,8 +167,25 @@ private constructor( this.preferences = preferences } - fun profile(profile: JsonValue) = apply { this.profile = profile } + /** + * User profile information. For email-based bulk jobs, `profile.email` is required for + * provider routing to determine if the message can be delivered. The email address should + * be provided here rather than in `to.email`. + */ + fun profile(profile: Profile?) = profile(JsonField.ofNullable(profile)) + + /** Alias for calling [Builder.profile] with `profile.orElse(null)`. */ + fun profile(profile: Optional) = profile(profile.getOrNull()) + /** + * Sets [Builder.profile] to an arbitrary JSON value. + * + * You should usually call [Builder.profile] with a well-typed [Profile] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun profile(profile: JsonField) = apply { this.profile = profile } + + /** User ID (legacy field, use profile or to.user_id instead) */ fun recipient(recipient: String?) = recipient(JsonField.ofNullable(recipient)) /** Alias for calling [Builder.recipient] with `recipient.orElse(null)`. */ @@ -159,6 +200,11 @@ private constructor( */ fun recipient(recipient: JsonField) = apply { this.recipient = recipient } + /** + * Optional recipient information. Note: For email provider routing, use `profile.email` + * instead of `to.email`. The `to` field is primarily used for recipient identification and + * data merging. + */ fun to(to: UserRecipient?) = to(JsonField.ofNullable(to)) /** Alias for calling [Builder.to] with `to.orElse(null)`. */ @@ -216,6 +262,7 @@ private constructor( } preferences().ifPresent { it.validate() } + profile().ifPresent { it.validate() } recipient() to().ifPresent { it.validate() } validated = true @@ -237,9 +284,114 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (preferences.asKnown().getOrNull()?.validity() ?: 0) + + (profile.asKnown().getOrNull()?.validity() ?: 0) + (if (recipient.asKnown().isPresent) 1 else 0) + (to.asKnown().getOrNull()?.validity() ?: 0) + /** + * User profile information. For email-based bulk jobs, `profile.email` is required for provider + * routing to determine if the message can be delivered. The email address should be provided + * here rather than in `to.email`. + */ + class Profile + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Profile]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Profile]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(profile: Profile) = apply { + additionalProperties = profile.additionalProperties.toMutableMap() + } + + 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 [Profile]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Profile = Profile(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): Profile = apply { + if (validated) { + return@apply + } + + 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 = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Profile && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Profile{additionalProperties=$additionalProperties}" + } + override fun equals(other: Any?): Boolean { if (this === other) { return true diff --git a/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt index a0129ce4..da6cb045 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageParams.kt @@ -1476,6 +1476,7 @@ private constructor( @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val duration: JsonField, + private val timezone: JsonField, private val until: JsonField, private val additionalProperties: MutableMap, ) { @@ -1485,8 +1486,11 @@ private constructor( @JsonProperty("duration") @ExcludeMissing duration: JsonField = JsonMissing.of(), + @JsonProperty("timezone") + @ExcludeMissing + timezone: JsonField = JsonMissing.of(), @JsonProperty("until") @ExcludeMissing until: JsonField = JsonMissing.of(), - ) : this(duration, until, mutableMapOf()) + ) : this(duration, timezone, until, mutableMapOf()) /** * The duration of the delay in milliseconds. @@ -1496,6 +1500,15 @@ private constructor( */ fun duration(): Optional = duration.getOptional("duration") + /** + * IANA timezone identifier (e.g., "America/Los_Angeles", "UTC"). Used when resolving + * opening hours expressions. Takes precedence over user profile timezone settings. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun timezone(): Optional = timezone.getOptional("timezone") + /** * ISO 8601 timestamp or opening_hours-like format. * @@ -1512,6 +1525,14 @@ private constructor( */ @JsonProperty("duration") @ExcludeMissing fun _duration(): JsonField = duration + /** + * Returns the raw JSON value of [timezone]. + * + * Unlike [timezone], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("timezone") @ExcludeMissing fun _timezone(): JsonField = timezone + /** * Returns the raw JSON value of [until]. * @@ -1541,12 +1562,14 @@ private constructor( class Builder internal constructor() { private var duration: JsonField = JsonMissing.of() + private var timezone: JsonField = JsonMissing.of() private var until: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(delay: Delay) = apply { duration = delay.duration + timezone = delay.timezone until = delay.until additionalProperties = delay.additionalProperties.toMutableMap() } @@ -1573,6 +1596,25 @@ private constructor( */ fun duration(duration: JsonField) = apply { this.duration = duration } + /** + * IANA timezone identifier (e.g., "America/Los_Angeles", "UTC"). Used when + * resolving opening hours expressions. Takes precedence over user profile timezone + * settings. + */ + fun timezone(timezone: String?) = timezone(JsonField.ofNullable(timezone)) + + /** Alias for calling [Builder.timezone] with `timezone.orElse(null)`. */ + fun timezone(timezone: Optional) = timezone(timezone.getOrNull()) + + /** + * Sets [Builder.timezone] to an arbitrary JSON value. + * + * You should usually call [Builder.timezone] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun timezone(timezone: JsonField) = apply { this.timezone = timezone } + /** ISO 8601 timestamp or opening_hours-like format. */ fun until(until: String?) = until(JsonField.ofNullable(until)) @@ -1615,7 +1657,8 @@ private constructor( * * Further updates to this [Builder] will not mutate the returned instance. */ - fun build(): Delay = Delay(duration, until, additionalProperties.toMutableMap()) + fun build(): Delay = + Delay(duration, timezone, until, additionalProperties.toMutableMap()) } private var validated: Boolean = false @@ -1626,6 +1669,7 @@ private constructor( } duration() + timezone() until() validated = true } @@ -1647,6 +1691,7 @@ private constructor( @JvmSynthetic internal fun validity(): Int = (if (duration.asKnown().isPresent) 1 else 0) + + (if (timezone.asKnown().isPresent) 1 else 0) + (if (until.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { @@ -1656,18 +1701,19 @@ private constructor( return other is Delay && duration == other.duration && + timezone == other.timezone && until == other.until && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(duration, until, additionalProperties) + Objects.hash(duration, timezone, until, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "Delay{duration=$duration, until=$until, additionalProperties=$additionalProperties}" + "Delay{duration=$duration, timezone=$timezone, until=$until, additionalProperties=$additionalProperties}" } class Expiry diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/BulkServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/BulkServiceAsync.kt index c34fcff9..5b82508a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/BulkServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/BulkServiceAsync.kt @@ -31,7 +31,12 @@ interface BulkServiceAsync { */ fun withOptions(modifier: Consumer): BulkServiceAsync - /** Ingest user data into a Bulk Job */ + /** + * Ingest user data into a Bulk Job. + * + * **Important**: For email-based bulk jobs, each user must include `profile.email` for provider + * routing to work correctly. The `to.email` field is not sufficient for email provider routing. + */ fun addUsers(jobId: String, params: BulkAddUsersParams): CompletableFuture = addUsers(jobId, params, RequestOptions.none()) @@ -52,7 +57,14 @@ interface BulkServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture - /** Create a bulk job */ + /** + * Creates a new bulk job for sending messages to multiple recipients. + * + * **Required**: `message.event` (event ID or notification ID) + * + * **Optional (V2 format)**: `message.template` (notification ID) or `message.content` + * (Elemental content) can be provided to override the notification associated with the event. + */ fun createJob(params: BulkCreateJobParams): CompletableFuture = createJob(params, RequestOptions.none()) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/BulkService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/BulkService.kt index 51a8e44d..25143807 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/BulkService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/BulkService.kt @@ -31,7 +31,12 @@ interface BulkService { */ fun withOptions(modifier: Consumer): BulkService - /** Ingest user data into a Bulk Job */ + /** + * Ingest user data into a Bulk Job. + * + * **Important**: For email-based bulk jobs, each user must include `profile.email` for provider + * routing to work correctly. The `to.email` field is not sufficient for email provider routing. + */ fun addUsers(jobId: String, params: BulkAddUsersParams) = addUsers(jobId, params, RequestOptions.none()) @@ -48,7 +53,14 @@ interface BulkService { /** @see addUsers */ fun addUsers(params: BulkAddUsersParams, requestOptions: RequestOptions = RequestOptions.none()) - /** Create a bulk job */ + /** + * Creates a new bulk job for sending messages to multiple recipients. + * + * **Required**: `message.event` (event ID or notification ID) + * + * **Optional (V2 format)**: `message.template` (notification ID) or `message.content` + * (Elemental content) can be provided to override the notification associated with the event. + */ fun createJob(params: BulkCreateJobParams): BulkCreateJobResponse = createJob(params, RequestOptions.none()) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkAddUsersParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkAddUsersParamsTest.kt index 6cabd8bd..d552754c 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkAddUsersParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkAddUsersParamsTest.kt @@ -64,7 +64,11 @@ internal class BulkAddUsersParamsTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() @@ -212,7 +216,11 @@ internal class BulkAddUsersParamsTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() @@ -346,7 +354,11 @@ internal class BulkAddUsersParamsTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() diff --git a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkCreateJobParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkCreateJobParamsTest.kt index ad18a5c5..4e379328 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkCreateJobParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkCreateJobParamsTest.kt @@ -3,6 +3,7 @@ package com.courier.models.bulk import com.courier.core.JsonValue +import com.courier.models.ElementalContentSugar import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -12,25 +13,26 @@ internal class BulkCreateJobParamsTest { fun create() { BulkCreateJobParams.builder() .message( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content(ElementalContentSugar.builder().body("body").title("title").build()) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() ) .build() @@ -41,25 +43,28 @@ internal class BulkCreateJobParamsTest { val params = BulkCreateJobParams.builder() .message( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content( + ElementalContentSugar.builder().body("body").title("title").build() + ) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() ) .build() @@ -68,28 +73,27 @@ internal class BulkCreateJobParamsTest { assertThat(body.message()) .isEqualTo( - InboundBulkMessage.ofTemplate( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") - .brand("brand") - .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .event("event") - .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() - .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) - .build() - ) - .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .build() - ) + InboundBulkMessage.builder() + .event("event") + .brand("brand") + .content(ElementalContentSugar.builder().body("body").title("title").build()) + .data( + InboundBulkMessage.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .locale( + InboundBulkMessage.Locale.builder() + .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) + .build() + ) + .override( + InboundBulkMessage.Override.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .template("template") + .build() ) } @@ -97,22 +101,11 @@ internal class BulkCreateJobParamsTest { fun bodyWithoutOptionalFields() { val params = BulkCreateJobParams.builder() - .message( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") - .build() - ) + .message(InboundBulkMessage.builder().event("event").build()) .build() val body = params._body() - assertThat(body.message()) - .isEqualTo( - InboundBulkMessage.ofTemplate( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") - .build() - ) - ) + assertThat(body.message()).isEqualTo(InboundBulkMessage.builder().event("event").build()) } } diff --git a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkListUsersResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkListUsersResponseTest.kt index a8ac9360..08c5c44f 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkListUsersResponseTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkListUsersResponseTest.kt @@ -71,7 +71,11 @@ internal class BulkListUsersResponseTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() @@ -206,7 +210,11 @@ internal class BulkListUsersResponseTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() @@ -344,7 +352,11 @@ internal class BulkListUsersResponseTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() diff --git a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkRetrieveJobResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkRetrieveJobResponseTest.kt index 198e8886..8f3c66c8 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkRetrieveJobResponseTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/bulk/BulkRetrieveJobResponseTest.kt @@ -4,6 +4,7 @@ package com.courier.models.bulk import com.courier.core.JsonValue import com.courier.core.jsonMapper +import com.courier.models.ElementalContentSugar import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -17,17 +18,22 @@ internal class BulkRetrieveJobResponseTest { .job( BulkRetrieveJobResponse.Job.builder() .definition( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content( + ElementalContentSugar.builder() + .body("body") + .title("title") + .build() + ) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty( "foo", JsonValue.from(mapOf("foo" to "bar")), @@ -35,10 +41,11 @@ internal class BulkRetrieveJobResponseTest { .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() ) .enqueued(0L) @@ -53,17 +60,19 @@ internal class BulkRetrieveJobResponseTest { .isEqualTo( BulkRetrieveJobResponse.Job.builder() .definition( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content( + ElementalContentSugar.builder().body("body").title("title").build() + ) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty( "foo", JsonValue.from(mapOf("foo" to "bar")), @@ -71,10 +80,11 @@ internal class BulkRetrieveJobResponseTest { .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() ) .enqueued(0L) @@ -93,17 +103,22 @@ internal class BulkRetrieveJobResponseTest { .job( BulkRetrieveJobResponse.Job.builder() .definition( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content( + ElementalContentSugar.builder() + .body("body") + .title("title") + .build() + ) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty( "foo", JsonValue.from(mapOf("foo" to "bar")), @@ -111,10 +126,11 @@ internal class BulkRetrieveJobResponseTest { .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() ) .enqueued(0L) diff --git a/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageTest.kt index d78db46d..9dce5d30 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageTest.kt @@ -4,140 +4,93 @@ package com.courier.models.bulk import com.courier.core.JsonValue import com.courier.core.jsonMapper -import com.courier.errors.CourierInvalidDataException import com.courier.models.ElementalContentSugar import com.fasterxml.jackson.module.kotlin.jacksonTypeRef import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.EnumSource internal class InboundBulkMessageTest { @Test - fun ofTemplate() { - val template = - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + fun create() { + val inboundBulkMessage = + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content(ElementalContentSugar.builder().body("body").title("title").build()) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() - val inboundBulkMessage = InboundBulkMessage.ofTemplate(template) - - assertThat(inboundBulkMessage.template()).contains(template) - assertThat(inboundBulkMessage.content()).isEmpty - } - - @Test - fun ofTemplateRoundtrip() { - val jsonMapper = jsonMapper() - val inboundBulkMessage = - InboundBulkMessage.ofTemplate( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") - .brand("brand") - .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .event("event") - .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() - .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) - .build() - ) - .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) + assertThat(inboundBulkMessage.event()).isEqualTo("event") + assertThat(inboundBulkMessage.brand()).contains("brand") + assertThat(inboundBulkMessage.content()) + .contains( + InboundBulkMessage.Content.ofElementalContentSugar( + ElementalContentSugar.builder().body("body").title("title").build() + ) + ) + assertThat(inboundBulkMessage.data()) + .contains( + InboundBulkMessage.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - - val roundtrippedInboundBulkMessage = - jsonMapper.readValue( - jsonMapper.writeValueAsString(inboundBulkMessage), - jacksonTypeRef(), + assertThat(inboundBulkMessage.locale()) + .contains( + InboundBulkMessage.Locale.builder() + .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) + .build() ) - - assertThat(roundtrippedInboundBulkMessage).isEqualTo(inboundBulkMessage) + assertThat(inboundBulkMessage.override()) + .contains( + InboundBulkMessage.Override.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + assertThat(inboundBulkMessage.template()).contains("template") } @Test - fun ofContent() { - val content = - InboundBulkMessage.InboundBulkContentMessage.builder() - .content(ElementalContentSugar.builder().body("body").title("title").build()) + fun roundtrip() { + val jsonMapper = jsonMapper() + val inboundBulkMessage = + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content(ElementalContentSugar.builder().body("body").title("title").build()) .data( - InboundBulkMessage.InboundBulkContentMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkContentMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) .build() ) .override( - InboundBulkMessage.InboundBulkContentMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() - val inboundBulkMessage = InboundBulkMessage.ofContent(content) - - assertThat(inboundBulkMessage.template()).isEmpty - assertThat(inboundBulkMessage.content()).contains(content) - } - - @Test - fun ofContentRoundtrip() { - val jsonMapper = jsonMapper() - val inboundBulkMessage = - InboundBulkMessage.ofContent( - InboundBulkMessage.InboundBulkContentMessage.builder() - .content(ElementalContentSugar.builder().body("body").title("title").build()) - .brand("brand") - .data( - InboundBulkMessage.InboundBulkContentMessage.Data.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .event("event") - .locale( - InboundBulkMessage.InboundBulkContentMessage.Locale.builder() - .putAdditionalProperty("foo", JsonValue.from(mapOf("foo" to "bar"))) - .build() - ) - .override( - InboundBulkMessage.InboundBulkContentMessage.Override.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .build() - ) - val roundtrippedInboundBulkMessage = jsonMapper.readValue( jsonMapper.writeValueAsString(inboundBulkMessage), @@ -146,22 +99,4 @@ internal class InboundBulkMessageTest { assertThat(roundtrippedInboundBulkMessage).isEqualTo(inboundBulkMessage) } - - enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { - BOOLEAN(JsonValue.from(false)), - STRING(JsonValue.from("invalid")), - INTEGER(JsonValue.from(-1)), - FLOAT(JsonValue.from(3.14)), - ARRAY(JsonValue.from(listOf("invalid", "array"))), - } - - @ParameterizedTest - @EnumSource - fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { - val inboundBulkMessage = - jsonMapper().convertValue(testCase.value, jacksonTypeRef()) - - val e = assertThrows { inboundBulkMessage.validate() } - assertThat(e).hasMessageStartingWith("Unknown ") - } } diff --git a/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageUserTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageUserTest.kt index 07fc5c7d..9757c99c 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageUserTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/bulk/InboundBulkMessageUserTest.kt @@ -58,7 +58,11 @@ internal class InboundBulkMessageUserTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() @@ -170,8 +174,12 @@ internal class InboundBulkMessageUserTest { ) .build() ) - assertThat(inboundBulkMessageUser._profile()) - .isEqualTo(JsonValue.from(mapOf())) + assertThat(inboundBulkMessageUser.profile()) + .contains( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) assertThat(inboundBulkMessageUser.recipient()).contains("recipient") assertThat(inboundBulkMessageUser.to()) .contains( @@ -288,7 +296,11 @@ internal class InboundBulkMessageUserTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() diff --git a/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt index c62d9ffb..877599c9 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageParamsTest.kt @@ -56,6 +56,7 @@ internal class SendMessageParamsTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -257,6 +258,7 @@ internal class SendMessageParamsTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -460,6 +462,7 @@ internal class SendMessageParamsTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt index 0823fcb9..0088168b 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/ErrorHandlingTest.kt @@ -123,6 +123,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -355,6 +356,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -587,6 +589,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -819,6 +822,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -1051,6 +1055,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -1283,6 +1288,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -1515,6 +1521,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -1747,6 +1754,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -1979,6 +1987,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -2211,6 +2220,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -2443,6 +2453,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -2675,6 +2686,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -2907,6 +2919,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -3139,6 +3152,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -3371,6 +3385,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -3603,6 +3618,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) @@ -3833,6 +3849,7 @@ internal class ErrorHandlingTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt index c08ecddd..cbb5798a 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/ServiceParamsTest.kt @@ -91,6 +91,7 @@ internal class ServiceParamsTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/BulkServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/BulkServiceAsyncTest.kt index 3b2d01c1..753e731f 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/BulkServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/BulkServiceAsyncTest.kt @@ -5,6 +5,7 @@ package com.courier.services.async import com.courier.TestServerExtension import com.courier.client.okhttp.CourierOkHttpClientAsync import com.courier.core.JsonValue +import com.courier.models.ElementalContentSugar import com.courier.models.MessageContext import com.courier.models.RecipientPreferences import com.courier.models.UserRecipient @@ -87,7 +88,11 @@ internal class BulkServiceAsyncTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() @@ -187,17 +192,19 @@ internal class BulkServiceAsyncTest { bulkServiceAsync.createJob( BulkCreateJobParams.builder() .message( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content( + ElementalContentSugar.builder().body("body").title("title").build() + ) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty( "foo", JsonValue.from(mapOf("foo" to "bar")), @@ -205,10 +212,11 @@ internal class BulkServiceAsyncTest { .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() ) .build() diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt index 06911327..b8d52beb 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/SendServiceAsyncTest.kt @@ -73,6 +73,7 @@ internal class SendServiceAsyncTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() ) diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/BulkServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/BulkServiceTest.kt index 3c6682e3..5b280605 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/BulkServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/BulkServiceTest.kt @@ -5,6 +5,7 @@ package com.courier.services.blocking import com.courier.TestServerExtension import com.courier.client.okhttp.CourierOkHttpClient import com.courier.core.JsonValue +import com.courier.models.ElementalContentSugar import com.courier.models.MessageContext import com.courier.models.RecipientPreferences import com.courier.models.UserRecipient @@ -86,7 +87,11 @@ internal class BulkServiceTest { ) .build() ) - .profile(JsonValue.from(mapOf())) + .profile( + InboundBulkMessageUser.Profile.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) .recipient("recipient") .to( UserRecipient.builder() @@ -184,17 +189,19 @@ internal class BulkServiceTest { bulkService.createJob( BulkCreateJobParams.builder() .message( - InboundBulkMessage.InboundBulkTemplateMessage.builder() - .template("template") + InboundBulkMessage.builder() + .event("event") .brand("brand") + .content( + ElementalContentSugar.builder().body("body").title("title").build() + ) .data( - InboundBulkMessage.InboundBulkTemplateMessage.Data.builder() + InboundBulkMessage.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) - .event("event") .locale( - InboundBulkMessage.InboundBulkTemplateMessage.Locale.builder() + InboundBulkMessage.Locale.builder() .putAdditionalProperty( "foo", JsonValue.from(mapOf("foo" to "bar")), @@ -202,10 +209,11 @@ internal class BulkServiceTest { .build() ) .override( - InboundBulkMessage.InboundBulkTemplateMessage.Override.builder() + InboundBulkMessage.Override.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .template("template") .build() ) .build() diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt index ea0e82e6..bb0f32f5 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/SendServiceTest.kt @@ -73,6 +73,7 @@ internal class SendServiceTest { .delay( SendMessageParams.Message.Delay.builder() .duration(0L) + .timezone("timezone") .until("until") .build() )