diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9acbd5b..66f75c90 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,10 +22,10 @@ jobs: if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: temurin java-version: | @@ -34,7 +34,7 @@ jobs: cache: gradle - name: Set up Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - name: Run lints run: ./scripts/lint @@ -49,10 +49,10 @@ jobs: if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: temurin java-version: | @@ -61,7 +61,7 @@ jobs: cache: gradle - name: Set up Gradle - uses: gradle/actions/setup-gradle@v4 + uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4.4.3 - name: Build SDK run: ./scripts/build @@ -71,7 +71,7 @@ jobs: github.repository == 'stainless-sdks/courier-java' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -91,10 +91,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/courier-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: temurin java-version: | @@ -103,7 +103,7 @@ jobs: cache: gradle - name: Set up Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 - name: Run tests run: ./scripts/test diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index 800d5266..54d4ca64 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -14,10 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Java - uses: actions/setup-java@v5 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: temurin java-version: | @@ -26,7 +26,7 @@ jobs: cache: gradle - name: Set up Gradle - uses: gradle/gradle-build-action@v2 + uses: gradle/gradle-build-action@a8f75513eafdebd8141bd1cd4e30fcd194af8dfa # v2.12.0 - name: Publish to Sonatype run: |- diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 2cc67736..6e6e244d 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'trycourier/courier-java' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | diff --git a/.release-please-manifest.json b/.release-please-manifest.json index ef0ce5df..a817334f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "4.13.1" + ".": "4.14.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index effa635e..17321d43 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 103 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier%2Fcourier-3f78581b4e078a1f620d9f587f18d77bcde6d20f56b0e4ae798648f4236494fb.yml -openapi_spec_hash: 6bd33e0396d85e11bb46f0d549af93a3 -config_hash: afcc4f6f8c33ca3f338589e32e086f56 +configured_endpoints: 117 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/courier/courier-8e7ad3d889c555ff9c381518b627b24b85e3eb7376bdc3689adc7a96ec78e537.yml +openapi_spec_hash: 53b3680aae719487c56efaa782bbe5b2 +config_hash: 10bd597dd6cc89023541bc551b6532b8 diff --git a/CHANGELOG.md b/CHANGELOG.md index 21698c5a..5183f029 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## 4.14.0 (2026-05-19) + +Full Changelog: [v4.13.1...v4.14.0](https://github.com/trycourier/courier-java/compare/v4.13.1...v4.14.0) + +### Features + +* [C-18276] Publish Journeys endpoints + types in openapi.yml ([5525cbd](https://github.com/trycourier/courier-java/commit/5525cbd0de6234ad4e5585a2255380d9f6e34b01)) +* [C-18380] Journeys API reference: copy + naming cleanup ([b0d0a7c](https://github.com/trycourier/courier-java/commit/b0d0a7c3260aa6afe98ae6430ef8485450faa401)) +* **client:** improve logging ([0ec8146](https://github.com/trycourier/courier-java/commit/0ec8146c41091a5e8a733dcd55796bcfb1e42a2d)) +* **client:** more robust error parsing ([dfddadd](https://github.com/trycourier/courier-java/commit/dfddadd8ab69cc9c7ec54c5a77ab749e6b9ef326)) +* **client:** support proxy authentication ([1970659](https://github.com/trycourier/courier-java/commit/1970659bdff9093f19ba2a0e9fd29e289d097503)) +* support setting headers via env ([0daaeb0](https://github.com/trycourier/courier-java/commit/0daaeb00073c63b431948f08180a83ba8103e74a)) +* Update requestId description and example in SendMessageResponse ([544f31a](https://github.com/trycourier/courier-java/commit/544f31a5494056540bd5cabe80d37810438ff580)) + + +### Performance Improvements + +* **client:** create one json mapper ([a32e5f0](https://github.com/trycourier/courier-java/commit/a32e5f01ad406002ddac7b6948d41ae08be49579)) + + +### Chores + +* **internal:** regenerate SDK with no functional changes ([ee2263b](https://github.com/trycourier/courier-java/commit/ee2263bb79e91190ef50f87e5fce97abe6600a4e)) +* **openapi:** bump requestId example to re-trigger docs sync ([61f5bd5](https://github.com/trycourier/courier-java/commit/61f5bd517e04455a1f26cbdcb2cc6cae5cfe6a85)) +* **openapi:** bump requestId example to re-trigger docs sync ([d8a85c7](https://github.com/trycourier/courier-java/commit/d8a85c7e81de7bd2b7390984eb421ff061b81b17)) +* redact api-key headers in debug logs ([abe8fea](https://github.com/trycourier/courier-java/commit/abe8feaef46775e0102015b1d34a772d90224f2f)) +* remove duplicated dokka setup ([124dc6d](https://github.com/trycourier/courier-java/commit/124dc6d37161a4cffd310a4ba87588422ee26681)) + + +### Documentation + +* clarify forwards compat behavior ([b830924](https://github.com/trycourier/courier-java/commit/b830924d986652432d1f063c110e55f32c601bcb)) + ## 4.13.1 (2026-04-14) Full Changelog: [v4.13.0...v4.13.1](https://github.com/trycourier/courier-java/compare/v4.13.0...v4.13.1) diff --git a/README.md b/README.md index d65d5327..0b3f0957 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,467 @@ var response = client.send().message(params); System.out.println(response.requestId()); ``` +## Error handling + +The SDK throws custom unchecked exception types: + +- [`CourierServiceException`](courier-java-core/src/main/kotlin/com/courier/errors/CourierServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code: + + | Status | Exception | + | ------ | ------------------------------------------------------------------------------------------------------------------------ | + | 400 | [`BadRequestException`](courier-java-core/src/main/kotlin/com/courier/errors/BadRequestException.kt) | + | 401 | [`UnauthorizedException`](courier-java-core/src/main/kotlin/com/courier/errors/UnauthorizedException.kt) | + | 403 | [`PermissionDeniedException`](courier-java-core/src/main/kotlin/com/courier/errors/PermissionDeniedException.kt) | + | 404 | [`NotFoundException`](courier-java-core/src/main/kotlin/com/courier/errors/NotFoundException.kt) | + | 422 | [`UnprocessableEntityException`](courier-java-core/src/main/kotlin/com/courier/errors/UnprocessableEntityException.kt) | + | 429 | [`RateLimitException`](courier-java-core/src/main/kotlin/com/courier/errors/RateLimitException.kt) | + | 5xx | [`InternalServerException`](courier-java-core/src/main/kotlin/com/courier/errors/InternalServerException.kt) | + | others | [`UnexpectedStatusCodeException`](courier-java-core/src/main/kotlin/com/courier/errors/UnexpectedStatusCodeException.kt) | + +- [`CourierIoException`](courier-java-core/src/main/kotlin/com/courier/errors/CourierIoException.kt): I/O networking errors. + +- [`CourierRetryableException`](courier-java-core/src/main/kotlin/com/courier/errors/CourierRetryableException.kt): Generic error indicating a failure that could be retried by the client. + +- [`CourierInvalidDataException`](courier-java-core/src/main/kotlin/com/courier/errors/CourierInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that's supposed to be required, but the API unexpectedly omitted it from the response. + +- [`CourierException`](courier-java-core/src/main/kotlin/com/courier/errors/CourierException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class. + +## Logging + +Enable logging by setting the `COURIER_LOG` environment variable to `info`: + +```sh +export COURIER_LOG=info +``` + +Or to `debug` for more verbose logging: + +```sh +export COURIER_LOG=debug +``` + +Or configure the client manually using the `logLevel` method: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; +import com.courier.core.LogLevel; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + .logLevel(LogLevel.INFO) + .build(); +``` + +## ProGuard and R8 + +Although the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `courier-java-core` is published with a [configuration file](courier-java-core/src/main/resources/META-INF/proguard/courier-java-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage). + +ProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary. + +## Jackson + +The SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default. + +The SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config). + +If the SDK threw an exception, but you're _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`CourierOkHttpClient`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt) or [`CourierOkHttpClientAsync`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt). + +> [!CAUTION] +> We make no guarantee that the SDK works correctly when the Jackson version check is disabled. + +Also note that there are bugs in older Jackson versions that can affect the SDK. We don't work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead. + +## Network options + +### Retries + +The SDK automatically retries 2 times by default, with a short exponential backoff between requests. + +Only the following error types are retried: + +- Connection errors (for example, due to a network connectivity problem) +- 408 Request Timeout +- 409 Conflict +- 429 Rate Limit +- 5xx Internal + +The API may also explicitly instruct the SDK to retry or not retry a request. + +To set a custom number of retries, configure the client using the `maxRetries` method: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + .maxRetries(4) + .build(); +``` + +### Timeouts + +Requests time out after 1 minute by default. + +To set a custom timeout, configure the method call using the `timeout` method: + +```java +import com.courier.models.send.SendMessageResponse; + +SendMessageResponse response = client.send().message( + params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build() +); +``` + +Or configure the default for all method calls at the client level: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; +import java.time.Duration; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + .timeout(Duration.ofSeconds(30)) + .build(); +``` + +### Proxies + +To route requests through a proxy, configure the client using the `proxy` method: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; +import java.net.InetSocketAddress; +import java.net.Proxy; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + .proxy(new Proxy( + Proxy.Type.HTTP, new InetSocketAddress( + "https://example.com", 8080 + ) + )) + .build(); +``` + +If the proxy responds with `407 Proxy Authentication Required`, supply credentials by also configuring `proxyAuthenticator`: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; +import com.courier.core.http.ProxyAuthenticator; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + .proxy(...) + // Or a custom implementation of `ProxyAuthenticator`. + .proxyAuthenticator(ProxyAuthenticator.basic("username", "password")) + .build(); +``` + +### Connection pooling + +To customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; +import java.time.Duration; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa. + .maxIdleConnections(10) + .keepAliveDuration(Duration.ofMinutes(2)) + .build(); +``` + +If both options are unset, OkHttp's default connection pool settings are used. + +### HTTPS + +> [!NOTE] +> Most applications should not call these methods, and instead use the system defaults. The defaults include +> special optimizations that can be lost if the implementations are modified. + +To configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa. + .sslSocketFactory(yourSSLSocketFactory) + .trustManager(yourTrustManager) + .hostnameVerifier(yourHostnameVerifier) + .build(); +``` + +### Custom HTTP client + +The SDK consists of three artifacts: + +- `courier-java-core` + - Contains core SDK logic + - Does not depend on [OkHttp](https://square.github.io/okhttp) + - Exposes [`CourierClient`](courier-java-core/src/main/kotlin/com/courier/client/CourierClient.kt), [`CourierClientAsync`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsync.kt), [`CourierClientImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt), and [`CourierClientAsyncImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt), all of which can work with any HTTP client +- `courier-java-client-okhttp` + - Depends on [OkHttp](https://square.github.io/okhttp) + - Exposes [`CourierOkHttpClient`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt) and [`CourierOkHttpClientAsync`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt), which provide a way to construct [`CourierClientImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt) and [`CourierClientAsyncImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt), respectively, using OkHttp +- `courier-java` + - Depends on and exposes the APIs of both `courier-java-core` and `courier-java-client-okhttp` + - Does not have its own logic + +This structure allows replacing the SDK's default HTTP client without pulling in unnecessary dependencies. + +#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html) + +> [!TIP] +> Try the available [network options](#network-options) before replacing the default client. + +To use a customized `OkHttpClient`: + +1. Replace your [`courier-java` dependency](#installation) with `courier-java-core` +2. Copy `courier-java-client-okhttp`'s [`OkHttpClient`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt) class into your code and customize it +3. Construct [`CourierClientImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt) or [`CourierClientAsyncImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt), similarly to [`CourierOkHttpClient`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt) or [`CourierOkHttpClientAsync`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt), using your customized client + +### Completely custom HTTP client + +To use a completely custom HTTP client: + +1. Replace your [`courier-java` dependency](#installation) with `courier-java-core` +2. Write a class that implements the [`HttpClient`](courier-java-core/src/main/kotlin/com/courier/core/http/HttpClient.kt) interface +3. Construct [`CourierClientImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientImpl.kt) or [`CourierClientAsyncImpl`](courier-java-core/src/main/kotlin/com/courier/client/CourierClientAsyncImpl.kt), similarly to [`CourierOkHttpClient`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt) or [`CourierOkHttpClientAsync`](courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt), using your new client class + +## Undocumented API functionality + +The SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API. + +### Parameters + +To set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class: + +```java +import com.courier.core.JsonValue; +import com.courier.models.send.SendMessageParams; + +SendMessageParams params = SendMessageParams.builder() + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") + .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) + .build(); +``` + +These can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods. + +To set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class: + +```java +import com.courier.core.JsonValue; +import com.courier.models.send.SendMessageParams; + +SendMessageParams params = SendMessageParams.builder() + .message(SendMessageParams.Message.builder() + .putAdditionalProperty("secretProperty", JsonValue.from("42")) + .build()) + .build(); +``` + +These properties can be accessed on the nested built object later using the `_additionalProperties()` method. + +To set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](courier-java-core/src/main/kotlin/com/courier/core/Values.kt) object to its setter: + +```java +import com.courier.core.JsonValue; +import com.courier.models.send.SendMessageParams; + +SendMessageParams params = SendMessageParams.builder() + .message(JsonValue.from(42)) + .build(); +``` + +The most straightforward way to create a [`JsonValue`](courier-java-core/src/main/kotlin/com/courier/core/Values.kt) is using its `from(...)` method: + +```java +import com.courier.core.JsonValue; +import java.util.List; +import java.util.Map; + +// Create primitive JSON values +JsonValue nullValue = JsonValue.from(null); +JsonValue booleanValue = JsonValue.from(true); +JsonValue numberValue = JsonValue.from(42); +JsonValue stringValue = JsonValue.from("Hello World!"); + +// Create a JSON array value equivalent to `["Hello", "World"]` +JsonValue arrayValue = JsonValue.from(List.of( + "Hello", "World" +)); + +// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }` +JsonValue objectValue = JsonValue.from(Map.of( + "a", 1, + "b", 2 +)); + +// Create an arbitrarily nested JSON equivalent to: +// { +// "a": [1, 2], +// "b": [3, 4] +// } +JsonValue complexValue = JsonValue.from(Map.of( + "a", List.of( + 1, 2 + ), + "b", List.of( + 3, 4 + ) +)); +``` + +Normally a `Builder` class's `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset. + +To forcibly omit a required parameter or property, pass [`JsonMissing`](courier-java-core/src/main/kotlin/com/courier/core/Values.kt): + +```java +import com.courier.core.JsonMissing; +import com.courier.models.send.SendMessageParams; + +SendMessageParams params = SendMessageParams.builder() + .message(JsonMissing.of()) + .build(); +``` + +### Response properties + +To access undocumented response properties, call the `_additionalProperties()` method: + +```java +import com.courier.core.JsonValue; +import java.util.Map; + +Map additionalProperties = client.send().message(params)._additionalProperties(); +JsonValue secretPropertyValue = additionalProperties.get("secretProperty"); + +String result = secretPropertyValue.accept(new JsonValue.Visitor<>() { + @Override + public String visitNull() { + return "It's null!"; + } + + @Override + public String visitBoolean(boolean value) { + return "It's a boolean!"; + } + + @Override + public String visitNumber(Number value) { + return "It's a number!"; + } + + // Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject` + // The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden +}); +``` + +To access a property's raw JSON value, which may be undocumented, call its `_` prefixed method: + +```java +import com.courier.core.JsonField; +import com.courier.models.send.SendMessageParams; +import java.util.Optional; + +JsonField message = client.send().message(params)._message(); + +if (message.isMissing()) { + // The property is absent from the JSON response +} else if (message.isNull()) { + // The property was set to literal null +} else { + // Check if value was provided as a string + // Other methods include `asNumber()`, `asBoolean()`, etc. + Optional jsonString = message.asString(); + + // Try to deserialize into a custom type + MyClass myObject = message.asUnknown().orElseThrow().convert(MyClass.class); +} +``` + +### Response validation + +In rare cases, the API may return a response that doesn't match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else. + +By default, the SDK will not throw an exception in this case. It will throw [`CourierInvalidDataException`](courier-java-core/src/main/kotlin/com/courier/errors/CourierInvalidDataException.kt) only if you directly access the property. + +Validating the response is _not_ forwards compatible with new types from the API for existing fields. + +If you would still prefer to check that the response is completely well-typed upfront, then either call `validate()`: + +```java +import com.courier.models.send.SendMessageResponse; + +SendMessageResponse response = client.send().message(params).validate(); +``` + +Or configure the method call to validate the response using the `responseValidation` method: + +```java +import com.courier.models.send.SendMessageResponse; + +SendMessageResponse response = client.send().message( + params, RequestOptions.builder().responseValidation(true).build() +); +``` + +Or configure the default for all method calls at the client level: + +```java +import com.courier.client.CourierClient; +import com.courier.client.okhttp.CourierOkHttpClient; + +CourierClient client = CourierOkHttpClient.builder() + .fromEnv() + .responseValidation(true) + .build(); +``` + +## FAQ + +### Why don't you use plain `enum` classes? + +Java `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value. + +### Why do you represent fields using `JsonField` instead of just plain `T`? + +Using `JsonField` enables a few features: + +- Allowing usage of [undocumented API functionality](#undocumented-api-functionality) +- Lazily [validating the API response against the expected shape](#response-validation) +- Representing absent vs explicitly null values + +### Why don't you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)? + +It is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don't want to introduce a breaking change every time we add a field to a class. + +### Why don't you use checked exceptions? + +Checked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason. + +Checked exceptions: + +- Are verbose to handle +- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error +- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function) +- Don't play well with lambdas (also due to the function coloring problem) + +## Semantic versioning + +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: The client reads `COURIER_API_KEY` from your environment (or `courier.apiKey` system property) automatically. ## Documentation diff --git a/build.gradle.kts b/build.gradle.kts index 5e5c1b36..d5fc2de8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.courier" - version = "4.13.1" // x-release-please-version + version = "4.14.0" // x-release-please-version } subprojects { @@ -21,7 +21,6 @@ subprojects { group = "Verification" description = "Verifies all source files are formatted." } - apply(plugin = "org.jetbrains.dokka") } subprojects { diff --git a/courier-java-client-okhttp/build.gradle.kts b/courier-java-client-okhttp/build.gradle.kts index 8bb8f619..813a96fa 100644 --- a/courier-java-client-okhttp/build.gradle.kts +++ b/courier-java-client-okhttp/build.gradle.kts @@ -7,7 +7,6 @@ dependencies { api(project(":courier-java-core")) implementation("com.squareup.okhttp3:okhttp:4.12.0") - implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") testImplementation(kotlin("test")) testImplementation("org.assertj:assertj-core:3.27.7") diff --git a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt index 73be7c55..13fcdf95 100644 --- a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt +++ b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClient.kt @@ -5,10 +5,12 @@ package com.courier.client.okhttp import com.courier.client.CourierClient import com.courier.client.CourierClientImpl import com.courier.core.ClientOptions +import com.courier.core.LogLevel import com.courier.core.Sleeper import com.courier.core.Timeout import com.courier.core.http.Headers import com.courier.core.http.HttpClient +import com.courier.core.http.ProxyAuthenticator import com.courier.core.http.QueryParams import com.courier.core.jsonMapper import com.fasterxml.jackson.databind.json.JsonMapper @@ -47,6 +49,7 @@ class CourierOkHttpClient private constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null + private var proxyAuthenticator: ProxyAuthenticator? = null private var maxIdleConnections: Int? = null private var keepAliveDuration: Duration? = null private var sslSocketFactory: SSLSocketFactory? = null @@ -77,6 +80,20 @@ class CourierOkHttpClient private constructor() { /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ fun proxy(proxy: Optional) = proxy(proxy.getOrNull()) + /** + * Provides credentials when an HTTP proxy responds with `407 Proxy Authentication + * Required`. + */ + fun proxyAuthenticator(proxyAuthenticator: ProxyAuthenticator?) = apply { + this.proxyAuthenticator = proxyAuthenticator + } + + /** + * Alias for calling [Builder.proxyAuthenticator] with `proxyAuthenticator.orElse(null)`. + */ + fun proxyAuthenticator(proxyAuthenticator: Optional) = + proxyAuthenticator(proxyAuthenticator.getOrNull()) + /** * The maximum number of idle connections kept by the underlying OkHttp connection pool. * @@ -217,6 +234,9 @@ class CourierOkHttpClient private constructor() { /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -258,6 +278,15 @@ class CourierOkHttpClient private constructor() { */ fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + fun logLevel(logLevel: LogLevel) = apply { clientOptions.logLevel(logLevel) } + fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) } fun headers(headers: Headers) = apply { clientOptions.headers(headers) } @@ -359,6 +388,7 @@ class CourierOkHttpClient private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .proxyAuthenticator(proxyAuthenticator) .maxIdleConnections(maxIdleConnections) .keepAliveDuration(keepAliveDuration) .dispatcherExecutorService(dispatcherExecutorService) diff --git a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt index 8a1baa2a..51ac8afc 100644 --- a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt +++ b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/CourierOkHttpClientAsync.kt @@ -5,10 +5,12 @@ package com.courier.client.okhttp import com.courier.client.CourierClientAsync import com.courier.client.CourierClientAsyncImpl import com.courier.core.ClientOptions +import com.courier.core.LogLevel import com.courier.core.Sleeper import com.courier.core.Timeout import com.courier.core.http.Headers import com.courier.core.http.HttpClient +import com.courier.core.http.ProxyAuthenticator import com.courier.core.http.QueryParams import com.courier.core.jsonMapper import com.fasterxml.jackson.databind.json.JsonMapper @@ -47,6 +49,7 @@ class CourierOkHttpClientAsync private constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null + private var proxyAuthenticator: ProxyAuthenticator? = null private var maxIdleConnections: Int? = null private var keepAliveDuration: Duration? = null private var sslSocketFactory: SSLSocketFactory? = null @@ -77,6 +80,20 @@ class CourierOkHttpClientAsync private constructor() { /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ fun proxy(proxy: Optional) = proxy(proxy.getOrNull()) + /** + * Provides credentials when an HTTP proxy responds with `407 Proxy Authentication + * Required`. + */ + fun proxyAuthenticator(proxyAuthenticator: ProxyAuthenticator?) = apply { + this.proxyAuthenticator = proxyAuthenticator + } + + /** + * Alias for calling [Builder.proxyAuthenticator] with `proxyAuthenticator.orElse(null)`. + */ + fun proxyAuthenticator(proxyAuthenticator: Optional) = + proxyAuthenticator(proxyAuthenticator.getOrNull()) + /** * The maximum number of idle connections kept by the underlying OkHttp connection pool. * @@ -217,6 +234,9 @@ class CourierOkHttpClientAsync private constructor() { /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -258,6 +278,15 @@ class CourierOkHttpClientAsync private constructor() { */ fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + fun logLevel(logLevel: LogLevel) = apply { clientOptions.logLevel(logLevel) } + fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) } fun headers(headers: Headers) = apply { clientOptions.headers(headers) } @@ -359,6 +388,7 @@ class CourierOkHttpClientAsync private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .proxyAuthenticator(proxyAuthenticator) .maxIdleConnections(maxIdleConnections) .keepAliveDuration(keepAliveDuration) .dispatcherExecutorService(dispatcherExecutorService) diff --git a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt index 86340f02..8c4ce441 100644 --- a/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt +++ b/courier-java-client-okhttp/src/main/kotlin/com/courier/client/okhttp/OkHttpClient.kt @@ -8,9 +8,11 @@ import com.courier.core.http.HttpMethod import com.courier.core.http.HttpRequest import com.courier.core.http.HttpRequestBody import com.courier.core.http.HttpResponse +import com.courier.core.http.ProxyAuthenticator import com.courier.errors.CourierIoException import java.io.IOException import java.io.InputStream +import java.io.OutputStream import java.net.Proxy import java.time.Duration import java.util.concurrent.CancellationException @@ -20,10 +22,12 @@ import java.util.concurrent.TimeUnit import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager +import kotlin.jvm.optionals.getOrNull import okhttp3.Call import okhttp3.Callback import okhttp3.ConnectionPool import okhttp3.Dispatcher +import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType @@ -31,8 +35,9 @@ import okhttp3.Request import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.Response -import okhttp3.logging.HttpLoggingInterceptor import okio.BufferedSink +import okio.buffer +import okio.sink class OkHttpClient internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient { @@ -41,7 +46,7 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie val call = newCall(request, requestOptions) return try { - call.execute().toResponse() + call.execute().toHttpResponse() } catch (e: IOException) { throw CourierIoException("Request failed", e) } finally { @@ -59,7 +64,7 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie call.enqueue( object : Callback { override fun onResponse(call: Call, response: Response) { - future.complete(response.toResponse()) + future.complete(response.toHttpResponse()) } override fun onFailure(call: Call, e: IOException) { @@ -87,18 +92,6 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call { val clientBuilder = okHttpClient.newBuilder() - val logLevel = - when (System.getenv("COURIER_LOG")?.lowercase()) { - "info" -> HttpLoggingInterceptor.Level.BASIC - "debug" -> HttpLoggingInterceptor.Level.BODY - else -> null - } - if (logLevel != null) { - clientBuilder.addNetworkInterceptor( - HttpLoggingInterceptor().setLevel(logLevel).apply { redactHeader("Authorization") } - ) - } - requestOptions.timeout?.let { clientBuilder .connectTimeout(it.connect()) @@ -111,89 +104,6 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie return client.newCall(request.toRequest(client)) } - private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient): Request { - var body: RequestBody? = body?.toRequestBody() - if (body == null && requiresBody(method)) { - body = "".toRequestBody() - } - - val builder = Request.Builder().url(toUrl()).method(method.name, body) - headers.names().forEach { name -> - headers.values(name).forEach { builder.addHeader(name, it) } - } - - if ( - !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0 - ) { - builder.addHeader( - "X-Stainless-Read-Timeout", - Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(), - ) - } - if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) { - builder.addHeader( - "X-Stainless-Timeout", - Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(), - ) - } - - return builder.build() - } - - /** `OkHttpClient` always requires a request body for some methods. */ - private fun requiresBody(method: HttpMethod): Boolean = - when (method) { - HttpMethod.POST, - HttpMethod.PUT, - HttpMethod.PATCH -> true - else -> false - } - - private fun HttpRequest.toUrl(): String { - val builder = baseUrl.toHttpUrl().newBuilder() - pathSegments.forEach(builder::addPathSegment) - queryParams.keys().forEach { key -> - queryParams.values(key).forEach { builder.addQueryParameter(key, it) } - } - - return builder.toString() - } - - private fun HttpRequestBody.toRequestBody(): RequestBody { - val mediaType = contentType()?.toMediaType() - val length = contentLength() - - return object : RequestBody() { - override fun contentType(): MediaType? = mediaType - - override fun contentLength(): Long = length - - override fun isOneShot(): Boolean = !repeatable() - - override fun writeTo(sink: BufferedSink) = writeTo(sink.outputStream()) - } - } - - private fun Response.toResponse(): HttpResponse { - val headers = headers.toHeaders() - - return object : HttpResponse { - override fun statusCode(): Int = code - - override fun headers(): Headers = headers - - override fun body(): InputStream = body!!.byteStream() - - override fun close() = body!!.close() - } - } - - private fun okhttp3.Headers.toHeaders(): Headers { - val headersBuilder = Headers.builder() - forEach { (name, value) -> headersBuilder.put(name, value) } - return headersBuilder.build() - } - companion object { @JvmStatic fun builder() = Builder() } @@ -202,6 +112,7 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie private var timeout: Timeout = Timeout.default() private var proxy: Proxy? = null + private var proxyAuthenticator: ProxyAuthenticator? = null private var maxIdleConnections: Int? = null private var keepAliveDuration: Duration? = null private var dispatcherExecutorService: ExecutorService? = null @@ -215,6 +126,10 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + fun proxyAuthenticator(proxyAuthenticator: ProxyAuthenticator?) = apply { + this.proxyAuthenticator = proxyAuthenticator + } + /** * Sets the maximum number of idle connections kept by the underlying [ConnectionPool]. * @@ -264,6 +179,19 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie .callTimeout(timeout.request()) .proxy(proxy) .apply { + proxyAuthenticator?.let { auth -> + proxyAuthenticator { route, response -> + auth + .authenticate( + route?.proxy ?: Proxy.NO_PROXY, + response.request.toHttpRequest(), + response.toHttpResponse(), + ) + .getOrNull() + ?.toRequest(client = null) + } + } + dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) } val maxIdleConnections = maxIdleConnections @@ -303,3 +231,126 @@ internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClie ) } } + +private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient?): Request { + var body: RequestBody? = body?.toRequestBody() + if (body == null && requiresBody(method)) { + body = "".toRequestBody() + } + + val builder = Request.Builder().url(toUrl()).method(method.name, body) + headers.names().forEach { name -> headers.values(name).forEach { builder.addHeader(name, it) } } + + if (client != null) { + if ( + !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0 + ) { + builder.addHeader( + "X-Stainless-Read-Timeout", + Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(), + ) + } + if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) { + builder.addHeader( + "X-Stainless-Timeout", + Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(), + ) + } + } + + return builder.build() +} + +/** `OkHttpClient` always requires a request body for some methods. */ +private fun requiresBody(method: HttpMethod): Boolean = + when (method) { + HttpMethod.POST, + HttpMethod.PUT, + HttpMethod.PATCH -> true + else -> false + } + +private fun HttpRequest.toUrl(): String { + val builder = baseUrl.toHttpUrl().newBuilder() + pathSegments.forEach(builder::addPathSegment) + queryParams.keys().forEach { key -> + queryParams.values(key).forEach { builder.addQueryParameter(key, it) } + } + + return builder.toString() +} + +private fun HttpRequestBody.toRequestBody(): RequestBody { + val mediaType = contentType()?.toMediaType() + val length = contentLength() + + return object : RequestBody() { + override fun contentType(): MediaType? = mediaType + + override fun contentLength(): Long = length + + override fun isOneShot(): Boolean = !repeatable() + + override fun writeTo(sink: BufferedSink) = writeTo(sink.outputStream()) + } +} + +private fun Request.toHttpRequest(): HttpRequest { + val builder = HttpRequest.builder().method(HttpMethod.valueOf(method)).baseUrl(url.toBaseUrl()) + url.pathSegments.forEach(builder::addPathSegment) + url.queryParameterNames.forEach { name -> + url.queryParameterValues(name).filterNotNull().forEach { builder.putQueryParam(name, it) } + } + headers.forEach { (name, value) -> builder.putHeader(name, value) } + body?.let { builder.body(it.toHttpRequestBody()) } + return builder.build() +} + +private fun HttpUrl.toBaseUrl(): String = buildString { + append(scheme).append("://").append(host) + if (port != HttpUrl.defaultPort(scheme)) { + append(":").append(port) + } +} + +private fun RequestBody.toHttpRequestBody(): HttpRequestBody { + val mediaType = contentType()?.toString() + val length = contentLength() + val isOneShot = isOneShot() + val source = this + return object : HttpRequestBody { + override fun contentType(): String? = mediaType + + override fun contentLength(): Long = length + + override fun repeatable(): Boolean = !isOneShot + + override fun writeTo(outputStream: OutputStream) { + val sink = outputStream.sink().buffer() + source.writeTo(sink) + sink.flush() + } + + override fun close() {} + } +} + +private fun Response.toHttpResponse(): HttpResponse { + val headers = headers.toHeaders() + + return object : HttpResponse { + override fun statusCode(): Int = code + + override fun headers(): Headers = headers + + override fun body(): InputStream = body!!.byteStream() + + override fun close() = body!!.close() + } +} + +private fun okhttp3.Headers.toHeaders(): Headers { + val headersBuilder = Headers.builder() + forEach { (name, value) -> headersBuilder.put(name, value) } + return headersBuilder.build() +} diff --git a/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt b/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt index bee20967..d630585b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt +++ b/courier-java-core/src/main/kotlin/com/courier/core/ClientOptions.kt @@ -4,6 +4,7 @@ package com.courier.core import com.courier.core.http.Headers import com.courier.core.http.HttpClient +import com.courier.core.http.LoggingHttpClient import com.courier.core.http.PhantomReachableClosingHttpClient import com.courier.core.http.QueryParams import com.courier.core.http.RetryingHttpClient @@ -66,6 +67,9 @@ private constructor( /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for existing + * fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -93,6 +97,14 @@ private constructor( * Defaults to 2. */ @get:JvmName("maxRetries") val maxRetries: Int, + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + @get:JvmName("logLevel") val logLevel: LogLevel, @get:JvmName("apiKey") val apiKey: String, ) { @@ -148,6 +160,7 @@ private constructor( private var responseValidation: Boolean = false private var timeout: Timeout = Timeout.default() private var maxRetries: Int = 2 + private var logLevel: LogLevel = LogLevel.fromEnv() private var apiKey: String? = null @JvmSynthetic @@ -163,6 +176,7 @@ private constructor( responseValidation = clientOptions.responseValidation timeout = clientOptions.timeout maxRetries = clientOptions.maxRetries + logLevel = clientOptions.logLevel apiKey = clientOptions.apiKey } @@ -229,6 +243,9 @@ private constructor( /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -270,6 +287,15 @@ private constructor( */ fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + fun logLevel(logLevel: LogLevel) = apply { this.logLevel = logLevel } + fun apiKey(apiKey: String) = apply { this.apiKey = apiKey } fun headers(headers: Headers) = apply { @@ -367,12 +393,21 @@ private constructor( * System properties take precedence over environment variables. */ fun fromEnv() = apply { + logLevel(LogLevel.fromEnv()) (System.getProperty("courier.baseUrl") ?: System.getenv("COURIER_BASE_URL"))?.let { baseUrl(it) } (System.getProperty("courier.apiKey") ?: System.getenv("COURIER_API_KEY"))?.let { apiKey(it) } + System.getenv("COURIER_CUSTOM_HEADERS")?.let { customHeadersEnv -> + for (line in customHeadersEnv.split("\n")) { + val colon = line.indexOf(':') + if (colon >= 0) { + putHeader(line.substring(0, colon).trim(), line.substring(colon + 1).trim()) + } + } + } } /** @@ -415,7 +450,13 @@ private constructor( return ClientOptions( httpClient, RetryingHttpClient.builder() - .httpClient(httpClient) + .httpClient( + LoggingHttpClient.builder() + .httpClient(httpClient) + .clock(clock) + .level(logLevel) + .build() + ) .sleeper(sleeper) .clock(clock) .maxRetries(maxRetries) @@ -430,6 +471,7 @@ private constructor( responseValidation, timeout, maxRetries, + logLevel, apiKey, ) } diff --git a/courier-java-core/src/main/kotlin/com/courier/core/LogLevel.kt b/courier-java-core/src/main/kotlin/com/courier/core/LogLevel.kt new file mode 100644 index 00000000..8e1d4c8b --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/core/LogLevel.kt @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.core + +/** The level at which to log request and response information. */ +enum class LogLevel { + /** No logging. */ + OFF, + /** Minimal request and response summary logs. No headers or bodies are logged. */ + INFO, + /** [INFO] logs plus details about request failures. */ + ERROR, + /** + * Full request and response logs. Sensitive headers are redacted, but sensitive data in request + * and response bodies may still be visible. + */ + DEBUG; + + /** Returns whether this level is at or higher than the given [level]. */ + fun shouldLog(level: LogLevel): Boolean = ordinal >= level.ordinal + + companion object { + + /** Returns a [LogLevel] based on the `COURIER_LOG` environment variable. */ + fun fromEnv() = + when (System.getenv("COURIER_LOG")?.lowercase()) { + "info" -> INFO + "error" -> ERROR + "debug" -> DEBUG + else -> OFF + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/core/ObjectMappers.kt b/courier-java-core/src/main/kotlin/com/courier/core/ObjectMappers.kt index feeda7fe..7c55b611 100644 --- a/courier-java-core/src/main/kotlin/com/courier/core/ObjectMappers.kt +++ b/courier-java-core/src/main/kotlin/com/courier/core/ObjectMappers.kt @@ -29,7 +29,9 @@ import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.temporal.ChronoField -fun jsonMapper(): JsonMapper = +fun jsonMapper(): JsonMapper = JSON_MAPPER + +private val JSON_MAPPER: JsonMapper = JsonMapper.builder() .addModule(kotlinModule()) .addModule(Jdk8Module()) diff --git a/courier-java-core/src/main/kotlin/com/courier/core/RequestOptions.kt b/courier-java-core/src/main/kotlin/com/courier/core/RequestOptions.kt index d09a60f8..bbf9f689 100644 --- a/courier-java-core/src/main/kotlin/com/courier/core/RequestOptions.kt +++ b/courier-java-core/src/main/kotlin/com/courier/core/RequestOptions.kt @@ -33,6 +33,15 @@ class RequestOptions private constructor(val responseValidation: Boolean?, val t private var responseValidation: Boolean? = null private var timeout: Timeout? = null + /** + * Whether to call `validate` on the response before returning it. + * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * + * Defaults to false, which means the shape of the response will not be validated upfront. + * Instead, validation will only occur for the parts of the response that are accessed. + */ fun responseValidation(responseValidation: Boolean) = apply { this.responseValidation = responseValidation } diff --git a/courier-java-core/src/main/kotlin/com/courier/core/Utils.kt b/courier-java-core/src/main/kotlin/com/courier/core/Utils.kt index f66d04fc..c8b2ec77 100644 --- a/courier-java-core/src/main/kotlin/com/courier/core/Utils.kt +++ b/courier-java-core/src/main/kotlin/com/courier/core/Utils.kt @@ -5,6 +5,7 @@ package com.courier.core import com.courier.errors.CourierInvalidDataException import java.util.Collections import java.util.SortedMap +import java.util.SortedSet import java.util.concurrent.CompletableFuture import java.util.concurrent.locks.Lock @@ -16,6 +17,11 @@ internal fun T?.getOrThrow(name: String): T = internal fun List.toImmutable(): List = if (isEmpty()) Collections.emptyList() else Collections.unmodifiableList(toList()) +@JvmSynthetic +internal fun > SortedSet.toImmutable(): SortedSet = + if (isEmpty()) Collections.emptySortedSet() + else Collections.unmodifiableSortedSet(toSortedSet(comparator() ?: Comparator.naturalOrder())) + @JvmSynthetic internal fun Map.toImmutable(): Map = if (isEmpty()) immutableEmptyMap() else Collections.unmodifiableMap(toMap()) diff --git a/courier-java-core/src/main/kotlin/com/courier/core/http/LoggingHttpClient.kt b/courier-java-core/src/main/kotlin/com/courier/core/http/LoggingHttpClient.kt new file mode 100644 index 00000000..b4e0d22b --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/core/http/LoggingHttpClient.kt @@ -0,0 +1,628 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.core.http + +import com.courier.core.LogLevel +import com.courier.core.RequestOptions +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import java.io.ByteArrayOutputStream +import java.io.InputStream +import java.io.OutputStream +import java.nio.ByteBuffer +import java.nio.charset.CharacterCodingException +import java.nio.charset.Charset +import java.nio.charset.CharsetDecoder +import java.nio.charset.CodingErrorAction +import java.nio.charset.StandardCharsets +import java.time.Clock +import java.time.Duration +import java.time.OffsetDateTime +import java.util.SortedSet +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CompletionException +import kotlin.time.toKotlinDuration + +/** A wrapper [HttpClient] around [httpClient] that logs request and response information. */ +class LoggingHttpClient +private constructor( + /** The underlying [HttpClient] for making requests. */ + @get:JvmName("httpClient") val httpClient: HttpClient, + /** + * Sensitive headers to redact from logs. + * + * Defaults to `Set.of("authorization", "api-key", "x-api-key", "cookie", "set-cookie")`. + */ + @get:JvmName("redactedHeaders") val redactedHeaders: SortedSet, + /** + * The clock to use for measuring request and response durations. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + @get:JvmName("clock") val clock: Clock, + /** + * The log level to use. + * + * Pass [LogLevel.fromEnv] to read from environment variables. + */ + @get:JvmName("level") val level: LogLevel, +) : HttpClient { + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { + val loggingRequest = logRequest(request) + + val before = OffsetDateTime.now(clock) + val response = + try { + httpClient.execute(loggingRequest, requestOptions) + } catch (e: Throwable) { + logFailure(e, Duration.between(before, OffsetDateTime.now(clock))) + throw e + } + + val took = Duration.between(before, OffsetDateTime.now(clock)) + return logResponse(response, took) + } + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture { + val loggingRequest = logRequest(request) + + val before = OffsetDateTime.now(clock) + val future = + try { + httpClient.executeAsync(loggingRequest, requestOptions) + } catch (e: Throwable) { + logFailure(e, Duration.between(before, OffsetDateTime.now(clock))) + throw e + } + return future.handle { response, error -> + val took = Duration.between(before, OffsetDateTime.now(clock)) + if (error != null) { + logFailure(unwrapCompletionException(error), took) + throw error + } + logResponse(response, took) + } + } + + private fun logRequest(request: HttpRequest): HttpRequest { + if (!level.shouldLog(LogLevel.INFO)) { + return request + } + + System.err.println( + buildString { + append("--> ${request.method} ${request.url()}") + request.body?.let { + val length = it.contentLength() + append(if (length >= 0) " ($length-byte body)" else " (unknown-length body)") + } + } + ) + + if (!level.shouldLog(LogLevel.DEBUG)) { + return request + } + + logHeaders(request.headers) + + if (request.body == null) { + System.err.println("--> END ${request.method}") + System.err.println() + return request + } + + return request + .toBuilder() + .body(LoggingHttpRequestBody(request.method, request.body)) + .build() + } + + private fun logResponse(response: HttpResponse, took: Duration): HttpResponse { + if (!level.shouldLog(LogLevel.INFO)) { + return response + } + + val contentLength = response.headers().values("Content-Length").firstOrNull()?.toIntOrNull() + System.err.println( + "<-- ${response.statusCode()} (${ + buildString { + append(took.format()) + contentLength?.let { append(", $contentLength-byte body") } + } + })" + ) + + if (!level.shouldLog(LogLevel.DEBUG)) { + return response + } + + logHeaders(response.headers()) + return LoggingHttpResponse(response) + } + + private fun logFailure(error: Throwable, took: Duration) { + if (!level.shouldLog(LogLevel.ERROR)) { + return + } + + System.err.println( + buildString { + append("<-- !! ${error.javaClass.simpleName}") + error.message?.let { append(": $it") } + append(" (${took.format()})") + } + ) + } + + private fun unwrapCompletionException(error: Throwable): Throwable = + if (error is CompletionException && error.cause != null) error.cause!! else error + + private fun logHeaders(headers: Headers) = + headers.names().forEach { name -> + headers.values(name).forEach { value -> + System.err.println("$name: ${if (redactedHeaders.contains(name)) "██" else value}") + } + } + + override fun close() = httpClient.close() + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [LoggingHttpClient]. + * + * The following fields are required: + * ```java + * .httpClient() + * .level() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LoggingHttpClient]. */ + class Builder internal constructor() { + + private var httpClient: HttpClient? = null + private var redactedHeaders: Set = + setOf("authorization", "api-key", "x-api-key", "cookie", "set-cookie") + private var clock: Clock = Clock.systemUTC() + private var level: LogLevel? = null + + @JvmSynthetic + internal fun from(loggingHttpClient: LoggingHttpClient) = apply { + httpClient = loggingHttpClient.httpClient + redactedHeaders = loggingHttpClient.redactedHeaders + clock = loggingHttpClient.clock + level = loggingHttpClient.level + } + + /** The underlying [HttpClient] for making requests. */ + fun httpClient(httpClient: HttpClient) = apply { this.httpClient = httpClient } + + /** + * Sensitive headers to redact from logs. + * + * Defaults to `Set.of("authorization", "api-key", "x-api-key", "cookie", "set-cookie")`. + */ + fun redactedHeaders(redactedHeaders: Set) = apply { + this.redactedHeaders = redactedHeaders + } + + /** + * The clock to use for measuring request and response durations. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { this.clock = clock } + + /** + * The log level to use. + * + * Pass [LogLevel.fromEnv] to read from environment variables. + */ + fun level(level: LogLevel) = apply { this.level = level } + + /** + * Returns an immutable instance of [LoggingHttpClient]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .httpClient() + * .level() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): LoggingHttpClient = + LoggingHttpClient( + checkRequired("httpClient", httpClient), + redactedHeaders.toSortedSet(String.CASE_INSENSITIVE_ORDER).toImmutable(), + clock, + checkRequired("level", level), + ) + } +} + +/** + * An [HttpRequestBody] wrapper that delegates to [body] while also logging line by line as it's + * written. + * + * The logging occurs in a streaming manner with minimal buffering. + */ +private class LoggingHttpRequestBody( + private val method: HttpMethod, + private val body: HttpRequestBody, +) : HttpRequestBody { + + private val charset by lazy { parseCharset(body.contentType()) } + + override fun writeTo(outputStream: OutputStream) { + val loggingOutputStream = LoggingOutputStream(outputStream, charset) + body.writeTo(loggingOutputStream) + + loggingOutputStream.flush() + System.err.println("--> END $method (${loggingOutputStream.writeCount()}-byte body)") + System.err.println() + } + + override fun contentType(): String? = body.contentType() + + override fun contentLength(): Long = body.contentLength() + + override fun repeatable(): Boolean = body.repeatable() + + override fun close() = body.close() +} + +/** + * An [OutputStream] wrapper that delegates to [outputStream] while also logging bytes line by line + * as it's written to. + * + * The written content is assumed to be in the given [charset] and the logging occurs in a streaming + * manner with minimal buffering. + */ +private class LoggingOutputStream(private val outputStream: OutputStream, charset: Charset?) : + OutputStream() { + + private val buffer = LoggingBuffer(charset) + + fun writeCount() = buffer.writeCount() + + override fun write(b: Int) { + outputStream.write(b) + buffer.write(b) + } + + override fun write(b: ByteArray, off: Int, len: Int) { + outputStream.write(b, off, len) + for (i in off until off + len) { + buffer.write(b[i].toInt() and 0xFF) + } + } + + /** Prints any currently buffered content. */ + override fun flush() { + buffer.flush() + outputStream.flush() + } + + override fun close() = outputStream.close() +} + +/** + * An [HttpResponse] wrapper that delegates to [response] while also logging line-by-line as it's + * read. + * + * The logging occurs in a streaming manner with minimal buffering. + */ +private class LoggingHttpResponse(private val response: HttpResponse) : HttpResponse { + + private val loggingBody: Lazy = lazy { + LoggingInputStream( + response.body(), + parseCharset(response.headers().values("Content-Type").firstOrNull()), + ) + } + + override fun statusCode(): Int = response.statusCode() + + override fun headers(): Headers = response.headers() + + override fun body(): InputStream = loggingBody.value + + override fun close() { + if (loggingBody.isInitialized()) { + loggingBody.value.close() + } + response.close() + } +} + +/** + * An [InputStream] wrapper that delegates to [inputStream] while also logging bytes line by line as + * it's read. + * + * The contents of [inputStream] are assumed to be in the given [charset] and the logging occurs in + * a streaming manner with minimal buffering. + */ +private class LoggingInputStream(private val inputStream: InputStream, charset: Charset?) : + InputStream() { + + private var isDone = false + private val buffer = LoggingBuffer(charset) + + override fun read(): Int { + if (isDone) { + return -1 + } + + val b = inputStream.read() + + if (b == -1) { + markDone() + return b + } + + buffer.write(b) + return b + } + + override fun read(b: ByteArray, off: Int, len: Int): Int { + if (isDone) { + return -1 + } + + val bytesRead = inputStream.read(b, off, len) + + if (bytesRead == -1) { + markDone() + return bytesRead + } + + for (i in off until off + bytesRead) { + buffer.write(b[i].toInt() and 0xFF) + } + return bytesRead + } + + override fun close() { + if (!isDone) { + markDone(closedEarly = true) + } + inputStream.close() + } + + private fun markDone(closedEarly: Boolean = false) { + isDone = true + buffer.flush() + val suffix = if (closedEarly) ", closed early" else "" + System.err.println("<-- END HTTP (${buffer.writeCount()}-byte body$suffix)") + System.err.println() + } +} + +/** + * A byte buffer that prints line by line, using the given [charset], as bytes are written to it. + * + * When [charset] is `null`, the buffer performs an upfront check to detect binary content. If + * non-whitespace ISO control characters are found in the first [PROBABLY_UTF8_CODE_POINT_LIMIT] + * code points, body logging is suppressed entirely. + */ +private class LoggingBuffer(charset: Charset?) { + + private val charset = charset ?: StandardCharsets.UTF_8 + + private val decoder: CharsetDecoder = + this.charset + .newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT) + private var writeCount = 0 + private val buffer = ByteArrayOutputStream(128) + + /** + * Whether logging has been suppressed because the content doesn't appear to be readable text. + * + * This is only set when [charset] is `null` and the content fails the [isProbablyUtf8] check. + */ + private var suppressed = false + + /** + * Bytes accumulated for the [isProbablyUtf8] check before any lines are printed. + * + * Once the check passes (or [charset] is non-null), this is set to `null` and bytes flow + * directly to [buffer]. + */ + private var prefetchBuffer: ByteArrayOutputStream? = + if (charset != null) null else ByteArrayOutputStream(128) + + fun writeCount() = writeCount + + fun write(b: Int) { + if (writeCount == 0) { + // Print a newline before we start printing anything to separate the printed content + // from previous content. + System.err.println() + } + + writeCount++ + + if (suppressed) { + return + } + + val prefetch = prefetchBuffer + if (prefetch != null) { + prefetch.write(b) + // Continue accumulating until we have enough bytes to decide. + if (prefetch.size() < PROBABLY_UTF8_BYTE_LIMIT && b != '\n'.code) { + return + } + // We have enough bytes. Check if the content is probably UTF-8. + prefetchBuffer = null + val bytes = prefetch.toByteArray() + if (!isProbablyUtf8(bytes)) { + suppressed = true + System.err.println("(binary body omitted)") + return + } + // Content looks like UTF-8. Feed the accumulated bytes into the normal buffer. + for (byte in bytes) { + writeToBuffer(byte.toInt() and 0xFF) + } + return + } + + writeToBuffer(b) + } + + private fun writeToBuffer(b: Int) { + if (b == '\n'.code) { + flush() + return + } + + buffer.write(b) + } + + /** Prints any currently buffered content. */ + fun flush() { + if (suppressed) { + return + } + + // If we still have a prefetch buffer when flush is called (body was shorter than the + // limit), run the check now. + val prefetch = prefetchBuffer + if (prefetch != null) { + prefetchBuffer = null + val bytes = prefetch.toByteArray() + if (bytes.isEmpty()) { + return + } + if (!isProbablyUtf8(bytes)) { + suppressed = true + System.err.println("(binary body omitted)") + return + } + for (byte in bytes) { + writeToBuffer(byte.toInt() and 0xFF) + } + } + + if (buffer.size() == 0) { + return + } + + val line = + try { + decoder.decode(ByteBuffer.wrap(buffer.toByteArray())) + } catch (e: CharacterCodingException) { + "(omitted line is not valid $charset)" + } + buffer.reset() + System.err.println(line) + } +} + +/** The maximum number of code points to sample when checking if content is probably UTF-8. */ +private const val PROBABLY_UTF8_CODE_POINT_LIMIT = 64 + +/** + * The maximum number of bytes to accumulate before running the [isProbablyUtf8] check. UTF-8 code + * points are at most 4 bytes, so this accommodates [PROBABLY_UTF8_CODE_POINT_LIMIT] code points. + */ +private const val PROBABLY_UTF8_BYTE_LIMIT = PROBABLY_UTF8_CODE_POINT_LIMIT * 4 + +/** + * Returns `true` if the given [bytes] probably contain human-readable UTF-8 text. + * + * Decodes up to [PROBABLY_UTF8_CODE_POINT_LIMIT] code points and returns `false` if any + * non-whitespace ISO control characters are found, or if the bytes are not valid UTF-8. + */ +private fun isProbablyUtf8(bytes: ByteArray): Boolean { + try { + val decoder = + StandardCharsets.UTF_8.newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT) + val charBuffer = decoder.decode(ByteBuffer.wrap(bytes)) + var codePointCount = 0 + var i = 0 + while (i < charBuffer.length && codePointCount < PROBABLY_UTF8_CODE_POINT_LIMIT) { + val codePoint = Character.codePointAt(charBuffer, i) + if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { + return false + } + i += Character.charCount(codePoint) + codePointCount++ + } + return true + } catch (e: CharacterCodingException) { + return false + } +} + +/** Returns the [Charset] in the given [contentType] string, or `null` if unspecified. */ +private fun parseCharset(contentType: String?): Charset? = + contentType + ?.split(";") + ?.drop(1) + ?.map { it.trim() } + ?.firstOrNull { it.startsWith("charset=", ignoreCase = true) } + ?.substringAfter("=") + ?.trim() + ?.removeSurrounding("\"") + ?.let { runCatching { charset(it) }.getOrNull() } + +/** Formats the [Duration] into a string like "1m 40s 467ms". */ +private fun Duration.format(): String = + toKotlinDuration().toComponents { days, hours, minutes, seconds, nanoseconds -> + buildString { + val milliseconds = nanoseconds / 1_000_000 + if (days > 0) { + append("${days}d") + } + if (hours > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${hours}h") + } + if (minutes > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${minutes}m") + } + if (seconds > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${seconds}s") + } + if (milliseconds > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${milliseconds}ms") + } + + if (isEmpty()) { + append("0s") + } + } + } diff --git a/courier-java-core/src/main/kotlin/com/courier/core/http/ProxyAuthenticator.kt b/courier-java-core/src/main/kotlin/com/courier/core/http/ProxyAuthenticator.kt new file mode 100644 index 00000000..1cc26365 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/core/http/ProxyAuthenticator.kt @@ -0,0 +1,59 @@ +package com.courier.core.http + +import java.net.Proxy +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets +import java.util.Base64 +import java.util.Optional + +/** + * Provides credentials when an HTTP proxy responds with `407 Proxy Authentication Required`. + * + * Implementations inspect the 407 [response] (typically its `Proxy-Authenticate` header) and return + * the request to retry with a `Proxy-Authorization` header set, or [Optional.empty] to abandon + * authentication and surface the 407 to the caller. + * + * Implementations must be thread-safe; they may be invoked concurrently from multiple HTTP calls. + */ +fun interface ProxyAuthenticator { + + /** + * @param proxy the proxy that produced the challenge, or [Proxy.NO_PROXY] if the route is not + * yet established + * @param request the request that produced [response] + * @param response the 407 challenge response + * @return the retry request to send (typically [request] with a `Proxy-Authorization` header + * added), or [Optional.empty] to abandon authentication + */ + fun authenticate( + proxy: Proxy, + request: HttpRequest, + response: HttpResponse, + ): Optional + + companion object { + + /** + * A [ProxyAuthenticator] that uses RFC 7617 Basic authentication with the ISO-8859-1 + * charset. + */ + @JvmStatic + fun basic(username: String, password: String): ProxyAuthenticator = + basic(username, password, StandardCharsets.ISO_8859_1) + + /** + * A [ProxyAuthenticator] that uses RFC 7617 Basic authentication with the given [charset]. + */ + @JvmStatic + fun basic(username: String, password: String, charset: Charset): ProxyAuthenticator { + val token = + Base64.getEncoder().encodeToString("$username:$password".toByteArray(charset)) + val headerValue = "Basic $token" + return ProxyAuthenticator { _, request, _ -> + Optional.of( + request.toBuilder().putHeader("Proxy-Authorization", headerValue).build() + ) + } + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/BadRequestException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/BadRequestException.kt index d1311bc3..18195b34 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/BadRequestException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/BadRequestException.kt @@ -5,12 +5,16 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class BadRequestException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - CourierServiceException("400: $body", cause) { + CourierServiceException( + "400: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 400 diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/InternalServerException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/InternalServerException.kt index 5cc7ad69..3d1011c9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/InternalServerException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/InternalServerException.kt @@ -5,6 +5,7 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,7 +15,11 @@ private constructor( private val headers: Headers, private val body: JsonValue, cause: Throwable?, -) : CourierServiceException("$statusCode: $body", cause) { +) : + CourierServiceException( + "$statusCode: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = statusCode diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/NotFoundException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/NotFoundException.kt index 25ac0ea0..b3a90d08 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/NotFoundException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/NotFoundException.kt @@ -5,12 +5,16 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class NotFoundException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - CourierServiceException("404: $body", cause) { + CourierServiceException( + "404: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 404 diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/PermissionDeniedException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/PermissionDeniedException.kt index 27a653bb..4ec3550a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/PermissionDeniedException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/PermissionDeniedException.kt @@ -5,12 +5,16 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class PermissionDeniedException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - CourierServiceException("403: $body", cause) { + CourierServiceException( + "403: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 403 diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/RateLimitException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/RateLimitException.kt index 7b6093a9..f5623b47 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/RateLimitException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/RateLimitException.kt @@ -5,12 +5,16 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class RateLimitException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - CourierServiceException("429: $body", cause) { + CourierServiceException( + "429: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 429 diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/UnauthorizedException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/UnauthorizedException.kt index a4f546a7..73605937 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/UnauthorizedException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/UnauthorizedException.kt @@ -5,12 +5,16 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class UnauthorizedException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - CourierServiceException("401: $body", cause) { + CourierServiceException( + "401: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 401 diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/UnexpectedStatusCodeException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/UnexpectedStatusCodeException.kt index d21851df..c3e4d0d5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/UnexpectedStatusCodeException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/UnexpectedStatusCodeException.kt @@ -5,6 +5,7 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,7 +15,11 @@ private constructor( private val headers: Headers, private val body: JsonValue, cause: Throwable?, -) : CourierServiceException("$statusCode: $body", cause) { +) : + CourierServiceException( + "$statusCode: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = statusCode diff --git a/courier-java-core/src/main/kotlin/com/courier/errors/UnprocessableEntityException.kt b/courier-java-core/src/main/kotlin/com/courier/errors/UnprocessableEntityException.kt index d4dc378e..2056dc18 100644 --- a/courier-java-core/src/main/kotlin/com/courier/errors/UnprocessableEntityException.kt +++ b/courier-java-core/src/main/kotlin/com/courier/errors/UnprocessableEntityException.kt @@ -5,12 +5,16 @@ package com.courier.errors import com.courier.core.JsonValue import com.courier.core.checkRequired import com.courier.core.http.Headers +import com.courier.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class UnprocessableEntityException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - CourierServiceException("422: $body", cause) { + CourierServiceException( + "422: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 422 diff --git a/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfile.kt b/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfile.kt index 73b3ae8f..c908c827 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfile.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfile.kt @@ -186,6 +186,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AirshipProfile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfileAudience.kt b/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfileAudience.kt index 3221dd9b..c8e089e6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfileAudience.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/AirshipProfileAudience.kt @@ -128,6 +128,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AirshipProfileAudience = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Alignment.kt b/courier-java-core/src/main/kotlin/com/courier/models/Alignment.kt index b96da083..530a68ae 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Alignment.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Alignment.kt @@ -104,6 +104,14 @@ class Alignment @JsonCreator private constructor(private val value: JsonField = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = discord.accept(new Discord.Visitor>() { + * @Override + * public Optional visitSendToChannel(SendToChannel sendToChannel) { + * return Optional.of(sendToChannel.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { sendToChannel != null -> visitor.visitSendToChannel(sendToChannel) @@ -50,6 +79,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Discord = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalActionNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalActionNodeWithType.kt index b1ba3ae9..24d1c080 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalActionNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalActionNodeWithType.kt @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalActionNodeWithType = apply { if (validated) { return@apply @@ -378,6 +386,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalBaseNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalBaseNode.kt index b4f7e024..75c12e86 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalBaseNode.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalBaseNode.kt @@ -229,6 +229,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalBaseNode = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNode.kt index 6b481f4c..b2c59726 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNode.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNode.kt @@ -315,6 +315,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalChannelNode = apply { if (validated) { return@apply @@ -412,6 +420,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Raw = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNodeWithType.kt index 6db19a3f..159bb5c7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalChannelNodeWithType.kt @@ -356,6 +356,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalChannelNodeWithType = apply { if (validated) { return@apply @@ -475,6 +483,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt index 037a7b41..16107598 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalContent.kt @@ -235,6 +235,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalContent = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalContentSugar.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalContentSugar.kt index 40684116..563b269a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalContentSugar.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalContentSugar.kt @@ -164,6 +164,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalContentSugar = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalDividerNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalDividerNodeWithType.kt index 0ebd0dab..7fdafdc8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalDividerNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalDividerNodeWithType.kt @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalDividerNodeWithType = apply { if (validated) { return@apply @@ -378,6 +386,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalHtmlNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalHtmlNodeWithType.kt index ad21b6ed..1f81b59d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalHtmlNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalHtmlNodeWithType.kt @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalHtmlNodeWithType = apply { if (validated) { return@apply @@ -378,6 +386,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalImageNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalImageNodeWithType.kt index 049d92f1..01627bc1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalImageNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalImageNodeWithType.kt @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalImageNodeWithType = apply { if (validated) { return@apply @@ -378,6 +386,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalMetaNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalMetaNodeWithType.kt index 324654aa..0a791d09 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalMetaNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalMetaNodeWithType.kt @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalMetaNodeWithType = apply { if (validated) { return@apply @@ -378,6 +386,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalNode.kt index 86580b8e..9028d345 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalNode.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalNode.kt @@ -132,6 +132,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = elementalNode.accept(new ElementalNode.Visitor>() { + * @Override + * public Optional visitTextNodeWithType(ElementalTextNodeWithType textNodeWithType) { + * return Optional.of(textNodeWithType.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { textNodeWithType != null -> visitor.visitTextNodeWithType(textNodeWithType) @@ -147,6 +176,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalNode = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalQuoteNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalQuoteNodeWithType.kt index 86e4cd41..b3133a34 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalQuoteNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalQuoteNodeWithType.kt @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalQuoteNodeWithType = apply { if (validated) { return@apply @@ -378,6 +386,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ElementalTextNodeWithType.kt b/courier-java-core/src/main/kotlin/com/courier/models/ElementalTextNodeWithType.kt index ed719c57..e891557c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ElementalTextNodeWithType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ElementalTextNodeWithType.kt @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementalTextNodeWithType = apply { if (validated) { return@apply @@ -378,6 +386,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Expo.kt b/courier-java-core/src/main/kotlin/com/courier/models/Expo.kt index ddbb6749..1991e762 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Expo.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Expo.kt @@ -41,6 +41,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = expo.accept(new Expo.Visitor>() { + * @Override + * public Optional visitToken(Token token) { + * return Optional.of(token.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { token != null -> visitor.visitToken(token) @@ -50,6 +79,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Expo = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/FilterConfig.kt b/courier-java-core/src/main/kotlin/com/courier/models/FilterConfig.kt index 6d0d0b29..d9c2cd0b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/FilterConfig.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/FilterConfig.kt @@ -267,6 +267,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): FilterConfig = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Intercom.kt b/courier-java-core/src/main/kotlin/com/courier/models/Intercom.kt index 23f38111..c1fb02ff 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Intercom.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Intercom.kt @@ -159,6 +159,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Intercom = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/IntercomRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/IntercomRecipient.kt index a37cccf7..11d3e0ca 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/IntercomRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/IntercomRecipient.kt @@ -124,6 +124,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): IntercomRecipient = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ListFilter.kt b/courier-java-core/src/main/kotlin/com/courier/models/ListFilter.kt index eff3d18e..636cc4bf 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ListFilter.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ListFilter.kt @@ -193,6 +193,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ListFilter = apply { if (validated) { return@apply @@ -305,6 +313,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply @@ -424,6 +441,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Path = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ListPatternRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/ListPatternRecipient.kt index 1feecfbb..f864d9ab 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ListPatternRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ListPatternRecipient.kt @@ -151,6 +151,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ListPatternRecipient = apply { if (validated) { return@apply @@ -237,6 +245,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/ListRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/ListRecipient.kt index 240e85ca..b1eae357 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/ListRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/ListRecipient.kt @@ -199,6 +199,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ListRecipient = apply { if (validated) { return@apply @@ -287,6 +295,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MessageChannels.kt b/courier-java-core/src/main/kotlin/com/courier/models/MessageChannels.kt index b685599d..e86906ef 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MessageChannels.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MessageChannels.kt @@ -68,6 +68,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageChannels = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MessageContext.kt b/courier-java-core/src/main/kotlin/com/courier/models/MessageContext.kt index 799634ae..e708cbd4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MessageContext.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MessageContext.kt @@ -116,6 +116,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageContext = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MessageProviders.kt b/courier-java-core/src/main/kotlin/com/courier/models/MessageProviders.kt index 00aab85b..93098306 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MessageProviders.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MessageProviders.kt @@ -68,6 +68,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageProviders = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MessageProvidersType.kt b/courier-java-core/src/main/kotlin/com/courier/models/MessageProvidersType.kt index fb44a55f..aba6734b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MessageProvidersType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MessageProvidersType.kt @@ -226,6 +226,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageProvidersType = apply { if (validated) { return@apply @@ -317,6 +325,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Override = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MessageRouting.kt b/courier-java-core/src/main/kotlin/com/courier/models/MessageRouting.kt index 00608822..0c1295e8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MessageRouting.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MessageRouting.kt @@ -190,6 +190,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageRouting = apply { if (validated) { return@apply @@ -305,6 +313,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Method = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MessageRoutingChannel.kt b/courier-java-core/src/main/kotlin/com/courier/models/MessageRoutingChannel.kt index 1a6a9359..36860213 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MessageRoutingChannel.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MessageRoutingChannel.kt @@ -41,6 +41,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = messageRoutingChannel.accept(new MessageRoutingChannel.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -50,6 +79,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageRoutingChannel = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Metadata.kt b/courier-java-core/src/main/kotlin/com/courier/models/Metadata.kt index 850328ce..37a0799a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Metadata.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Metadata.kt @@ -113,6 +113,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MsTeams.kt b/courier-java-core/src/main/kotlin/com/courier/models/MsTeams.kt index 9ad592ab..e72c2b0b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MsTeams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MsTeams.kt @@ -71,6 +71,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = msTeams.accept(new MsTeams.Visitor>() { + * @Override + * public Optional visitSendToMsTeamsUserId(SendToMsTeamsUserId sendToMsTeamsUserId) { + * return Optional.of(sendToMsTeamsUserId.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { sendToMsTeamsUserId != null -> visitor.visitSendToMsTeamsUserId(sendToMsTeamsUserId) @@ -86,6 +115,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MsTeams = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsBaseProperties.kt b/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsBaseProperties.kt index ff1e3117..017d3c7f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsBaseProperties.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsBaseProperties.kt @@ -160,6 +160,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MsTeamsBaseProperties = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsRecipient.kt index d48bee43..06e6db72 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MsTeamsRecipient.kt @@ -157,6 +157,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MsTeamsRecipient = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/MultipleTokens.kt b/courier-java-core/src/main/kotlin/com/courier/models/MultipleTokens.kt index d5627aff..9d6dac50 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/MultipleTokens.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/MultipleTokens.kt @@ -145,6 +145,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MultipleTokens = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/NotificationPreferenceDetails.kt b/courier-java-core/src/main/kotlin/com/courier/models/NotificationPreferenceDetails.kt index 28082294..631c14ed 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/NotificationPreferenceDetails.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/NotificationPreferenceDetails.kt @@ -236,6 +236,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationPreferenceDetails = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Pagerduty.kt b/courier-java-core/src/main/kotlin/com/courier/models/Pagerduty.kt index acedab0e..7912cff0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Pagerduty.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Pagerduty.kt @@ -218,6 +218,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Pagerduty = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/PagerdutyRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/PagerdutyRecipient.kt index c4060b51..5bcdc250 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/PagerdutyRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/PagerdutyRecipient.kt @@ -132,6 +132,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PagerdutyRecipient = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Paging.kt b/courier-java-core/src/main/kotlin/com/courier/models/Paging.kt index b6c304f1..79cbe0d4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Paging.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Paging.kt @@ -156,6 +156,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Paging = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Preference.kt b/courier-java-core/src/main/kotlin/com/courier/models/Preference.kt index 58f2dd3c..aa17d5f3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Preference.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Preference.kt @@ -266,6 +266,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Preference = apply { if (validated) { return@apply @@ -391,6 +399,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Source = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/PreferenceStatus.kt b/courier-java-core/src/main/kotlin/com/courier/models/PreferenceStatus.kt index f6c31381..d7d49b0f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/PreferenceStatus.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/PreferenceStatus.kt @@ -101,6 +101,14 @@ class PreferenceStatus @JsonCreator private constructor(private val value: JsonF private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PreferenceStatus = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/RecipientPreferences.kt b/courier-java-core/src/main/kotlin/com/courier/models/RecipientPreferences.kt index e07926cd..adef46d3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/RecipientPreferences.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/RecipientPreferences.kt @@ -159,6 +159,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): RecipientPreferences = apply { if (validated) { return@apply @@ -245,6 +253,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Categories = apply { if (validated) { return@apply @@ -344,6 +361,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Notifications = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Rule.kt b/courier-java-core/src/main/kotlin/com/courier/models/Rule.kt index 32cf4ac4..be7e0ccc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Rule.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Rule.kt @@ -156,6 +156,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Rule = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendDirectMessage.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendDirectMessage.kt index 2fa7a39c..5e1e46b1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendDirectMessage.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendDirectMessage.kt @@ -124,6 +124,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendDirectMessage = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToChannel.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToChannel.kt index 360010e2..d53e6fb2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToChannel.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToChannel.kt @@ -128,6 +128,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToChannel = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelId.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelId.kt index 867e2bf2..2d41c02e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelId.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelId.kt @@ -191,6 +191,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToMsTeamsChannelId = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelName.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelName.kt index 9fed8864..7f69ba4f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelName.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsChannelName.kt @@ -225,6 +225,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToMsTeamsChannelName = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsConversationId.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsConversationId.kt index 350af3a0..e7d9fc5a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsConversationId.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsConversationId.kt @@ -197,6 +197,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToMsTeamsConversationId = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsEmail.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsEmail.kt index be1dcfb8..02df06e8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsEmail.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsEmail.kt @@ -190,6 +190,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToMsTeamsEmail = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsUserId.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsUserId.kt index ce4fb3b7..662bc3c1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsUserId.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToMsTeamsUserId.kt @@ -190,6 +190,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToMsTeamsUserId = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackChannel.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackChannel.kt index 67b87ff7..5973449f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackChannel.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackChannel.kt @@ -162,6 +162,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToSlackChannel = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackEmail.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackEmail.kt index 0a2654a2..c06d31e6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackEmail.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackEmail.kt @@ -162,6 +162,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToSlackEmail = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackUserId.kt b/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackUserId.kt index 72c79ff6..41bdf510 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackUserId.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SendToSlackUserId.kt @@ -162,6 +162,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendToSlackUserId = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Slack.kt b/courier-java-core/src/main/kotlin/com/courier/models/Slack.kt index 1bc642e0..aaec986f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Slack.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Slack.kt @@ -49,6 +49,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = slack.accept(new Slack.Visitor>() { + * @Override + * public Optional visitSendToSlackChannel(SendToSlackChannel sendToSlackChannel) { + * return Optional.of(sendToSlackChannel.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { sendToSlackChannel != null -> visitor.visitSendToSlackChannel(sendToSlackChannel) @@ -59,6 +88,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Slack = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SlackBaseProperties.kt b/courier-java-core/src/main/kotlin/com/courier/models/SlackBaseProperties.kt index 32405d86..038a75a7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SlackBaseProperties.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SlackBaseProperties.kt @@ -132,6 +132,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SlackBaseProperties = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/SlackRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/SlackRecipient.kt index 4453cb81..4d831ee9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/SlackRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/SlackRecipient.kt @@ -138,6 +138,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SlackRecipient = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/TextStyle.kt b/courier-java-core/src/main/kotlin/com/courier/models/TextStyle.kt index e079f4fa..c3b7ad03 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/TextStyle.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/TextStyle.kt @@ -104,6 +104,14 @@ class TextStyle @JsonCreator private constructor(private val value: JsonField = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = userProfileFirebaseToken.accept(new UserProfileFirebaseToken.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -51,6 +80,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): UserProfileFirebaseToken = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/UserRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/UserRecipient.kt index 01ace678..65d0d305 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/UserRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/UserRecipient.kt @@ -454,6 +454,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): UserRecipient = apply { if (validated) { return@apply @@ -556,6 +564,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -792,6 +809,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Preferences = apply { if (validated) { return@apply @@ -884,6 +910,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Notifications = apply { if (validated) { return@apply @@ -986,6 +1022,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Categories = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/Utm.kt b/courier-java-core/src/main/kotlin/com/courier/models/Utm.kt index dc2f0da7..6e455e6c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/Utm.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/Utm.kt @@ -234,6 +234,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Utm = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthMode.kt b/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthMode.kt index baec95bb..da020d70 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthMode.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthMode.kt @@ -101,6 +101,14 @@ class WebhookAuthMode @JsonCreator private constructor(private val value: JsonFi private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): WebhookAuthMode = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthentication.kt b/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthentication.kt index 9883e9fa..b3c63abd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthentication.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/WebhookAuthentication.kt @@ -235,6 +235,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): WebhookAuthentication = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/WebhookMethod.kt b/courier-java-core/src/main/kotlin/com/courier/models/WebhookMethod.kt index 582cf21a..f1a5bfea 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/WebhookMethod.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/WebhookMethod.kt @@ -94,6 +94,14 @@ class WebhookMethod @JsonCreator private constructor(private val value: JsonFiel private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): WebhookMethod = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfile.kt b/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfile.kt index eba2a34d..c4eef438 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfile.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfile.kt @@ -287,6 +287,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): WebhookProfile = apply { if (validated) { return@apply @@ -380,6 +388,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Headers = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfileType.kt b/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfileType.kt index b6483a41..d502444c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfileType.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/WebhookProfileType.kt @@ -96,6 +96,14 @@ class WebhookProfileType @JsonCreator private constructor(private val value: Jso private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): WebhookProfileType = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/WebhookRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/WebhookRecipient.kt index 52893c35..ac517164 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/WebhookRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/WebhookRecipient.kt @@ -129,6 +129,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): WebhookRecipient = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/Audience.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/Audience.kt index a40c978a..8f321681 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/Audience.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/Audience.kt @@ -334,6 +334,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Audience = apply { if (validated) { return@apply @@ -460,6 +468,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersResponse.kt index 09ca5365..91661999 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListMembersResponse.kt @@ -174,6 +174,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AudienceListMembersResponse = apply { if (validated) { return@apply @@ -453,6 +461,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Item = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListResponse.kt index 83438ccb..b0cd26dc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceListResponse.kt @@ -174,6 +174,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AudienceListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt index 3344d3a4..4835ad3e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateParams.kt @@ -561,6 +561,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -705,6 +714,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateResponse.kt index c6185bcc..15b2e027 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/audiences/AudienceUpdateResponse.kt @@ -129,6 +129,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AudienceUpdateResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEvent.kt b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEvent.kt index b09997c1..dce49835 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEvent.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEvent.kt @@ -287,6 +287,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuditEvent = apply { if (validated) { return@apply @@ -464,6 +472,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Actor = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListResponse.kt index f07173b1..474b6a50 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/auditevents/AuditEventListResponse.kt @@ -178,6 +178,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuditEventListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt index 4698b92a..b6ae485d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenParams.kt @@ -522,6 +522,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenResponse.kt index b6771e70..9ecf433b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/auth/AuthIssueTokenResponse.kt @@ -127,6 +127,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthIssueTokenResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationInvokeResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationInvokeResponse.kt index 204a2386..73b1b059 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationInvokeResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationInvokeResponse.kt @@ -127,6 +127,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AutomationInvokeResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt index 0dd2a646..a72e9024 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationListParams.kt @@ -298,6 +298,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Version = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplate.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplate.kt index 940ff12c..53d02161 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplate.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplate.kt @@ -272,6 +272,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AutomationTemplate = apply { if (validated) { return@apply @@ -394,6 +402,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Version = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplateListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplateListResponse.kt index bfb155f8..52425a17 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplateListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/AutomationTemplateListResponse.kt @@ -170,6 +170,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AutomationTemplateListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt index 2bac3dba..22e3716c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeAdHocParams.kt @@ -676,6 +676,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -949,6 +958,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Automation = apply { if (validated) { return@apply @@ -1048,6 +1066,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, + * unless [visitor] overrides [Visitor.unknown]. To handle variants not known to this + * version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = step.accept(new Step.Visitor>() { + * @Override + * public Optional visitAutomationDelay(AutomationDelayStep automationDelay) { + * return Optional.of(automationDelay.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { automationDelay != null -> visitor.visitAutomationDelay(automationDelay) @@ -1065,6 +1113,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Step = apply { if (validated) { return@apply @@ -1527,6 +1585,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): AutomationDelayStep = apply { if (validated) { return@apply @@ -1647,6 +1715,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Action = apply { if (validated) { return@apply @@ -2011,6 +2089,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): AutomationSendStep = apply { if (validated) { return@apply @@ -2137,6 +2225,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Action = apply { if (validated) { return@apply @@ -2238,6 +2336,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -2343,6 +2451,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply @@ -2645,6 +2763,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): AutomationSendListStep = apply { if (validated) { return@apply @@ -2767,6 +2895,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Action = apply { if (validated) { return@apply @@ -2868,6 +3006,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -3170,6 +3318,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): AutomationUpdateProfileStep = apply { if (validated) { return@apply @@ -3292,6 +3450,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Action = apply { if (validated) { return@apply @@ -3393,6 +3561,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply @@ -3543,6 +3721,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Merge = apply { if (validated) { return@apply @@ -3767,6 +3955,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): AutomationCancelStep = apply { if (validated) { return@apply @@ -3885,6 +4083,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Action = apply { if (validated) { return@apply @@ -4148,6 +4356,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): AutomationFetchDataStep = apply { if (validated) { return@apply @@ -4268,6 +4486,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Action = apply { if (validated) { return@apply @@ -4537,6 +4765,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Webhook = apply { if (validated) { return@apply @@ -4685,6 +4923,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Method = apply { if (validated) { return@apply @@ -4789,6 +5037,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Headers = apply { if (validated) { return@apply @@ -4961,6 +5219,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): MergeStrategy = apply { if (validated) { return@apply @@ -5181,6 +5449,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): AutomationInvokeStep = apply { if (validated) { return@apply @@ -5299,6 +5577,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Action = apply { if (validated) { return@apply @@ -5439,6 +5727,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -5538,6 +5835,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt index aa22b765..7aa2fcbe 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/automations/invoke/InvokeInvokeByTemplateParams.kt @@ -617,6 +617,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -734,6 +743,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -833,6 +851,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/Brand.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/Brand.kt index ed406458..8e1f97cc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/Brand.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/Brand.kt @@ -356,6 +356,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Brand = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandColors.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandColors.kt index 5e0091e2..3cb8320e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandColors.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandColors.kt @@ -138,6 +138,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandColors = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt index 9bef07b4..4011e940 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandCreateParams.kt @@ -540,6 +540,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListResponse.kt index 01e98949..0d76bb82 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandListResponse.kt @@ -176,6 +176,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettings.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettings.kt index 8d2fc511..e604b1bb 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettings.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettings.kt @@ -181,6 +181,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandSettings = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsEmail.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsEmail.kt index 8b138dde..b6d34e04 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsEmail.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsEmail.kt @@ -224,6 +224,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandSettingsEmail = apply { if (validated) { return@apply @@ -731,6 +739,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TemplateOverride = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsInApp.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsInApp.kt index 8e5488fa..2eeb65ff 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsInApp.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSettingsInApp.kt @@ -367,6 +367,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandSettingsInApp = apply { if (validated) { return@apply @@ -506,6 +514,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Placement = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippet.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippet.kt index 1a9c5511..c26cd1ec 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippet.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippet.kt @@ -157,6 +157,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandSnippet = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippets.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippets.kt index 4d264941..ac76d52d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippets.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandSnippets.kt @@ -134,6 +134,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandSnippets = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandTemplate.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandTemplate.kt index 808f0faa..c8485f42 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandTemplate.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandTemplate.kt @@ -347,6 +347,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BrandTemplate = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt index fac80ebd..b4ebfb3d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/BrandUpdateParams.kt @@ -504,6 +504,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailFooter.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailFooter.kt index fac66313..69ea105f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailFooter.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailFooter.kt @@ -160,6 +160,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmailFooter = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHead.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHead.kt index 114036e8..3c81475b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHead.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHead.kt @@ -167,6 +167,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmailHead = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHeader.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHeader.kt index d620698c..fc8c5ec6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHeader.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/EmailHeader.kt @@ -207,6 +207,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmailHeader = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/Icons.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/Icons.kt index 8188f5ab..6d87744b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/Icons.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/Icons.kt @@ -143,6 +143,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Icons = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/Logo.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/Logo.kt index 522b5360..faa6c732 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/Logo.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/Logo.kt @@ -143,6 +143,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Logo = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/brands/WidgetBackground.kt b/courier-java-core/src/main/kotlin/com/courier/models/brands/WidgetBackground.kt index dde9a724..0c2611fb 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/brands/WidgetBackground.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/brands/WidgetBackground.kt @@ -147,6 +147,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): WidgetBackground = apply { if (validated) { return@apply 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 9fc953d9..65800113 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 @@ -403,6 +403,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply 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 573990e5..3af5ff9b 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 @@ -383,6 +383,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobResponse.kt index f1ab2975..02b06eb5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/bulk/BulkCreateJobResponse.kt @@ -127,6 +127,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BulkCreateJobResponse = apply { if (validated) { return@apply 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 287867e1..2023b33d 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 @@ -178,6 +178,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BulkListUsersResponse = apply { if (validated) { return@apply @@ -547,6 +555,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Item = apply { if (validated) { return@apply @@ -681,6 +698,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Status = apply { if (validated) { return@apply 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 5dc1e0b1..dc7e61b8 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 @@ -126,6 +126,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BulkRetrieveJobResponse = apply { if (validated) { return@apply @@ -404,6 +412,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Job = apply { if (validated) { return@apply @@ -542,6 +559,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Status = apply { if (validated) { return@apply 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 9960181e..6eaba94f 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 @@ -369,6 +369,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): InboundBulkMessage = apply { if (validated) { return@apply @@ -438,6 +446,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = content.accept(new Content.Visitor>() { + * @Override + * public Optional visitElementalContentSugar(ElementalContentSugar elementalContentSugar) { + * return Optional.of(elementalContentSugar.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { elementalContentSugar != null -> @@ -448,6 +485,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Content = apply { if (validated) { return@apply @@ -659,6 +705,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -758,6 +813,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Locale = apply { if (validated) { return@apply @@ -857,6 +921,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Override = apply { if (validated) { return@apply 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 be725b34..26a116b7 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 @@ -263,6 +263,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): InboundBulkMessageUser = apply { if (validated) { return@apply @@ -358,6 +366,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt index 65d6dac3..52c2c1e4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventParams.kt @@ -630,6 +630,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -747,6 +756,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Properties = apply { if (validated) { return@apply @@ -869,6 +887,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventResponse.kt index aca947de..965d87f7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/inbound/InboundTrackEventResponse.kt @@ -134,6 +134,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): InboundTrackEventResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/CreateJourneyRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/CreateJourneyRequest.kt new file mode 100644 index 00000000..91479db3 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/CreateJourneyRequest.kt @@ -0,0 +1,345 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Request body for creating a journey. */ +class CreateJourneyRequest +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val name: JsonField, + private val nodes: JsonField>, + private val enabled: JsonField, + private val state: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("nodes") + @ExcludeMissing + nodes: JsonField> = JsonMissing.of(), + @JsonProperty("enabled") @ExcludeMissing enabled: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + ) : this(name, nodes, enabled, state, 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). + */ + fun name(): String = name.getRequired("name") + + /** + * @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 nodes(): List = nodes.getRequired("nodes") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun enabled(): Optional = enabled.getOptional("enabled") + + /** + * Lifecycle state of a journey. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun state(): Optional = state.getOptional("state") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [nodes]. + * + * Unlike [nodes], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nodes") @ExcludeMissing fun _nodes(): JsonField> = nodes + + /** + * Returns the raw JSON value of [enabled]. + * + * Unlike [enabled], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("enabled") @ExcludeMissing fun _enabled(): JsonField = enabled + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [CreateJourneyRequest]. + * + * The following fields are required: + * ```java + * .name() + * .nodes() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [CreateJourneyRequest]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var nodes: JsonField>? = null + private var enabled: JsonField = JsonMissing.of() + private var state: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(createJourneyRequest: CreateJourneyRequest) = apply { + name = createJourneyRequest.name + nodes = createJourneyRequest.nodes.map { it.toMutableList() } + enabled = createJourneyRequest.enabled + state = createJourneyRequest.state + additionalProperties = createJourneyRequest.additionalProperties.toMutableMap() + } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun nodes(nodes: List) = nodes(JsonField.of(nodes)) + + /** + * Sets [Builder.nodes] to an arbitrary JSON value. + * + * You should usually call [Builder.nodes] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun nodes(nodes: JsonField>) = apply { + this.nodes = nodes.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyNode] to [nodes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addNode(node: JourneyNode) = apply { + nodes = + (nodes ?: JsonField.of(mutableListOf())).also { checkKnown("nodes", it).add(node) } + } + + /** Alias for calling [addNode] with `JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)`. */ + fun addNode(apiInvokeTrigger: JourneyApiInvokeTriggerNode) = + addNode(JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)) + + /** Alias for calling [addNode] with `JourneyNode.ofSegmentTrigger(segmentTrigger)`. */ + fun addNode(segmentTrigger: JourneySegmentTriggerNode) = + addNode(JourneyNode.ofSegmentTrigger(segmentTrigger)) + + /** Alias for calling [addNode] with `JourneyNode.ofSend(send)`. */ + fun addNode(send: JourneySendNode) = addNode(JourneyNode.ofSend(send)) + + /** Alias for calling [addNode] with `JourneyNode.ofDelayDuration(delayDuration)`. */ + fun addNode(delayDuration: JourneyDelayDurationNode) = + addNode(JourneyNode.ofDelayDuration(delayDuration)) + + /** Alias for calling [addNode] with `JourneyNode.ofDelayUntil(delayUntil)`. */ + fun addNode(delayUntil: JourneyDelayUntilNode) = + addNode(JourneyNode.ofDelayUntil(delayUntil)) + + /** Alias for calling [addNode] with `JourneyNode.ofFetchGetDelete(fetchGetDelete)`. */ + fun addNode(fetchGetDelete: JourneyFetchGetDeleteNode) = + addNode(JourneyNode.ofFetchGetDelete(fetchGetDelete)) + + /** Alias for calling [addNode] with `JourneyNode.ofFetchPostPut(fetchPostPut)`. */ + fun addNode(fetchPostPut: JourneyFetchPostPutNode) = + addNode(JourneyNode.ofFetchPostPut(fetchPostPut)) + + /** Alias for calling [addNode] with `JourneyNode.ofAi(ai)`. */ + fun addNode(ai: JourneyAiNode) = addNode(JourneyNode.ofAi(ai)) + + /** Alias for calling [addNode] with `JourneyNode.ofThrottleStatic(throttleStatic)`. */ + fun addNode(throttleStatic: JourneyThrottleStaticNode) = + addNode(JourneyNode.ofThrottleStatic(throttleStatic)) + + /** Alias for calling [addNode] with `JourneyNode.ofThrottleDynamic(throttleDynamic)`. */ + fun addNode(throttleDynamic: JourneyThrottleDynamicNode) = + addNode(JourneyNode.ofThrottleDynamic(throttleDynamic)) + + /** Alias for calling [addNode] with `JourneyNode.ofExit(exit)`. */ + fun addNode(exit: JourneyExitNode) = addNode(JourneyNode.ofExit(exit)) + + /** Alias for calling [addNode] with `JourneyNode.ofBranch(branch)`. */ + fun addNode(branch: JourneyNode.JourneyBranchNode) = addNode(JourneyNode.ofBranch(branch)) + + fun enabled(enabled: Boolean) = enabled(JsonField.of(enabled)) + + /** + * Sets [Builder.enabled] to an arbitrary JSON value. + * + * You should usually call [Builder.enabled] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun enabled(enabled: JsonField) = apply { this.enabled = enabled } + + /** Lifecycle state of a journey. */ + fun state(state: JourneyState) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [JourneyState] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun state(state: JsonField) = apply { this.state = state } + + 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 [CreateJourneyRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .name() + * .nodes() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): CreateJourneyRequest = + CreateJourneyRequest( + checkRequired("name", name), + checkRequired("nodes", nodes).map { it.toImmutable() }, + enabled, + state, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): CreateJourneyRequest = apply { + if (validated) { + return@apply + } + + name() + nodes().forEach { it.validate() } + enabled() + state().ifPresent { it.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 = + (if (name.asKnown().isPresent) 1 else 0) + + (nodes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (enabled.asKnown().isPresent) 1 else 0) + + (state.asKnown().getOrNull()?.validity() ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is CreateJourneyRequest && + name == other.name && + nodes == other.nodes && + enabled == other.enabled && + state == other.state && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(name, nodes, enabled, state, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "CreateJourneyRequest{name=$name, nodes=$nodes, enabled=$enabled, state=$state, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/Journey.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/Journey.kt index 71feee7c..2fb32625 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/Journey.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/Journey.kt @@ -273,6 +273,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Journey = apply { if (validated) { return@apply @@ -395,6 +403,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Version = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyAiNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyAiNode.kt new file mode 100644 index 00000000..a3a6f9f4 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyAiNode.kt @@ -0,0 +1,674 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Invoke an AI step with `user_prompt` and optional `web_search`. Returns a structured response + * conforming to `output_schema`. + */ +class JourneyAiNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val outputSchema: JsonField, + private val type: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val model: JsonField, + private val userPrompt: JsonField, + private val webSearch: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("output_schema") + @ExcludeMissing + outputSchema: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + @JsonProperty("model") @ExcludeMissing model: JsonField = JsonMissing.of(), + @JsonProperty("user_prompt") + @ExcludeMissing + userPrompt: JsonField = JsonMissing.of(), + @JsonProperty("web_search") @ExcludeMissing webSearch: JsonField = JsonMissing.of(), + ) : this(outputSchema, type, id, conditions, model, userPrompt, webSearch, mutableMapOf()) + + /** + * A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. + * + * @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 outputSchema(): OutputSchema = outputSchema.getRequired("output_schema") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun model(): Optional = model.getOptional("model") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun userPrompt(): Optional = userPrompt.getOptional("user_prompt") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun webSearch(): Optional = webSearch.getOptional("web_search") + + /** + * Returns the raw JSON value of [outputSchema]. + * + * Unlike [outputSchema], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("output_schema") + @ExcludeMissing + fun _outputSchema(): JsonField = outputSchema + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + /** + * Returns the raw JSON value of [model]. + * + * Unlike [model], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** + * Returns the raw JSON value of [userPrompt]. + * + * Unlike [userPrompt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("user_prompt") @ExcludeMissing fun _userPrompt(): JsonField = userPrompt + + /** + * Returns the raw JSON value of [webSearch]. + * + * Unlike [webSearch], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("web_search") @ExcludeMissing fun _webSearch(): JsonField = webSearch + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyAiNode]. + * + * The following fields are required: + * ```java + * .outputSchema() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyAiNode]. */ + class Builder internal constructor() { + + private var outputSchema: JsonField? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var userPrompt: JsonField = JsonMissing.of() + private var webSearch: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyAiNode: JourneyAiNode) = apply { + outputSchema = journeyAiNode.outputSchema + type = journeyAiNode.type + id = journeyAiNode.id + conditions = journeyAiNode.conditions + model = journeyAiNode.model + userPrompt = journeyAiNode.userPrompt + webSearch = journeyAiNode.webSearch + additionalProperties = journeyAiNode.additionalProperties.toMutableMap() + } + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + fun outputSchema(outputSchema: OutputSchema) = outputSchema(JsonField.of(outputSchema)) + + /** + * Sets [Builder.outputSchema] to an arbitrary JSON value. + * + * You should usually call [Builder.outputSchema] with a well-typed [OutputSchema] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun outputSchema(outputSchema: JsonField) = apply { + this.outputSchema = outputSchema + } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + fun model(model: String) = model(JsonField.of(model)) + + /** + * Sets [Builder.model] to an arbitrary JSON value. + * + * You should usually call [Builder.model] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun model(model: JsonField) = apply { this.model = model } + + fun userPrompt(userPrompt: String) = userPrompt(JsonField.of(userPrompt)) + + /** + * Sets [Builder.userPrompt] to an arbitrary JSON value. + * + * You should usually call [Builder.userPrompt] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun userPrompt(userPrompt: JsonField) = apply { this.userPrompt = userPrompt } + + fun webSearch(webSearch: Boolean) = webSearch(JsonField.of(webSearch)) + + /** + * Sets [Builder.webSearch] to an arbitrary JSON value. + * + * You should usually call [Builder.webSearch] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun webSearch(webSearch: JsonField) = apply { this.webSearch = webSearch } + + 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 [JourneyAiNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .outputSchema() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyAiNode = + JourneyAiNode( + checkRequired("outputSchema", outputSchema), + checkRequired("type", type), + id, + conditions, + model, + userPrompt, + webSearch, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyAiNode = apply { + if (validated) { + return@apply + } + + outputSchema().validate() + type().validate() + id() + conditions().ifPresent { it.validate() } + model() + userPrompt() + webSearch() + 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 = + (outputSchema.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + (if (model.asKnown().isPresent) 1 else 0) + + (if (userPrompt.asKnown().isPresent) 1 else 0) + + (if (webSearch.asKnown().isPresent) 1 else 0) + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + class OutputSchema + @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 [OutputSchema]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [OutputSchema]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(outputSchema: OutputSchema) = apply { + additionalProperties = outputSchema.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 [OutputSchema]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OutputSchema = OutputSchema(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): OutputSchema = 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 OutputSchema && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "OutputSchema{additionalProperties=$additionalProperties}" + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val AI = of("ai") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + AI + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + AI, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + AI -> Value.AI + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + AI -> Known.AI + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyAiNode && + outputSchema == other.outputSchema && + type == other.type && + id == other.id && + conditions == other.conditions && + model == other.model && + userPrompt == other.userPrompt && + webSearch == other.webSearch && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + outputSchema, + type, + id, + conditions, + model, + userPrompt, + webSearch, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyAiNode{outputSchema=$outputSchema, type=$type, id=$id, conditions=$conditions, model=$model, userPrompt=$userPrompt, webSearch=$webSearch, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyApiInvokeTriggerNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyApiInvokeTriggerNode.kt new file mode 100644 index 00000000..01d1b4be --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyApiInvokeTriggerNode.kt @@ -0,0 +1,730 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Trigger fired when the journey is invoked via the API. The optional `schema` field is a JSON + * Schema that validates the invocation payload. + */ +class JourneyApiInvokeTriggerNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val triggerType: JsonField, + private val type: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val schema: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("trigger_type") + @ExcludeMissing + triggerType: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + @JsonProperty("schema") @ExcludeMissing schema: JsonField = JsonMissing.of(), + ) : this(triggerType, type, id, conditions, schema, 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). + */ + fun triggerType(): TriggerType = triggerType.getRequired("trigger_type") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun schema(): Optional = schema.getOptional("schema") + + /** + * Returns the raw JSON value of [triggerType]. + * + * Unlike [triggerType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("trigger_type") + @ExcludeMissing + fun _triggerType(): JsonField = triggerType + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + /** + * Returns the raw JSON value of [schema]. + * + * Unlike [schema], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("schema") @ExcludeMissing fun _schema(): JsonField = schema + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyApiInvokeTriggerNode]. + * + * The following fields are required: + * ```java + * .triggerType() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyApiInvokeTriggerNode]. */ + class Builder internal constructor() { + + private var triggerType: JsonField? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var schema: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyApiInvokeTriggerNode: JourneyApiInvokeTriggerNode) = apply { + triggerType = journeyApiInvokeTriggerNode.triggerType + type = journeyApiInvokeTriggerNode.type + id = journeyApiInvokeTriggerNode.id + conditions = journeyApiInvokeTriggerNode.conditions + schema = journeyApiInvokeTriggerNode.schema + additionalProperties = journeyApiInvokeTriggerNode.additionalProperties.toMutableMap() + } + + fun triggerType(triggerType: TriggerType) = triggerType(JsonField.of(triggerType)) + + /** + * Sets [Builder.triggerType] to an arbitrary JSON value. + * + * You should usually call [Builder.triggerType] with a well-typed [TriggerType] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun triggerType(triggerType: JsonField) = apply { + this.triggerType = triggerType + } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + fun schema(schema: Schema) = schema(JsonField.of(schema)) + + /** + * Sets [Builder.schema] to an arbitrary JSON value. + * + * You should usually call [Builder.schema] with a well-typed [Schema] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun schema(schema: JsonField) = apply { this.schema = schema } + + 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 [JourneyApiInvokeTriggerNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .triggerType() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyApiInvokeTriggerNode = + JourneyApiInvokeTriggerNode( + checkRequired("triggerType", triggerType), + checkRequired("type", type), + id, + conditions, + schema, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyApiInvokeTriggerNode = apply { + if (validated) { + return@apply + } + + triggerType().validate() + type().validate() + id() + conditions().ifPresent { it.validate() } + schema().ifPresent { it.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 = + (triggerType.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + (schema.asKnown().getOrNull()?.validity() ?: 0) + + class TriggerType @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val API_INVOKE = of("api-invoke") + + @JvmStatic fun of(value: String) = TriggerType(JsonField.of(value)) + } + + /** An enum containing [TriggerType]'s known values. */ + enum class Known { + API_INVOKE + } + + /** + * An enum containing [TriggerType]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TriggerType] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + API_INVOKE, + /** + * An enum member indicating that [TriggerType] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + API_INVOKE -> Value.API_INVOKE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + API_INVOKE -> Known.API_INVOKE + else -> throw CourierInvalidDataException("Unknown TriggerType: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): TriggerType = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TriggerType && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val TRIGGER = of("trigger") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + TRIGGER + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + TRIGGER, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + TRIGGER -> Value.TRIGGER + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + TRIGGER -> Known.TRIGGER + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + class Schema + @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 [Schema]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Schema]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(schema: Schema) = apply { + additionalProperties = schema.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 [Schema]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Schema = Schema(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Schema = 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 Schema && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Schema{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyApiInvokeTriggerNode && + triggerType == other.triggerType && + type == other.type && + id == other.id && + conditions == other.conditions && + schema == other.schema && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(triggerType, type, id, conditions, schema, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyApiInvokeTriggerNode{triggerType=$triggerType, type=$type, id=$id, conditions=$conditions, schema=$schema, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyArchiveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyArchiveParams.kt new file mode 100644 index 00000000..ddb3f327 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyArchiveParams.kt @@ -0,0 +1,232 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Archive a journey. Archived journeys cannot be invoked. Existing journey runs continue to + * completion. + */ +class JourneyArchiveParams +private constructor( + private val templateId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): JourneyArchiveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [JourneyArchiveParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyArchiveParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyArchiveParams: JourneyArchiveParams) = apply { + templateId = journeyArchiveParams.templateId + additionalHeaders = journeyArchiveParams.additionalHeaders.toBuilder() + additionalQueryParams = journeyArchiveParams.additionalQueryParams.toBuilder() + additionalBodyProperties = journeyArchiveParams.additionalBodyProperties.toMutableMap() + } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [JourneyArchiveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyArchiveParams = + JourneyArchiveParams( + templateId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyArchiveParams && + templateId == other.templateId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(templateId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "JourneyArchiveParams{templateId=$templateId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionGroup.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionGroup.kt new file mode 100644 index 00000000..73f35a57 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionGroup.kt @@ -0,0 +1,230 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * A leaf condition group. Exactly one of `AND` or `OR` must be present at runtime; each is a list + * of `JourneyConditionAtom` tuples. + */ +class JourneyConditionGroup +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val and: JsonField>>, + private val or: JsonField>>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("AND") @ExcludeMissing and: JsonField>> = JsonMissing.of(), + @JsonProperty("OR") @ExcludeMissing or: JsonField>> = JsonMissing.of(), + ) : this(and, or, mutableMapOf()) + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun and(): Optional>> = and.getOptional("AND") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun or(): Optional>> = or.getOptional("OR") + + /** + * Returns the raw JSON value of [and]. + * + * Unlike [and], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("AND") @ExcludeMissing fun _and(): JsonField>> = and + + /** + * Returns the raw JSON value of [or]. + * + * Unlike [or], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("OR") @ExcludeMissing fun _or(): JsonField>> = or + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [JourneyConditionGroup]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyConditionGroup]. */ + class Builder internal constructor() { + + private var and: JsonField>>? = null + private var or: JsonField>>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyConditionGroup: JourneyConditionGroup) = apply { + and = journeyConditionGroup.and.map { it.toMutableList() } + or = journeyConditionGroup.or.map { it.toMutableList() } + additionalProperties = journeyConditionGroup.additionalProperties.toMutableMap() + } + + fun and(and: List>) = and(JsonField.of(and)) + + /** + * Sets [Builder.and] to an arbitrary JSON value. + * + * You should usually call [Builder.and] with a well-typed `List>` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun and(and: JsonField>>) = apply { + this.and = and.map { it.toMutableList() } + } + + /** + * Adds a single [List] to [Builder.and]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAnd(and: List) = apply { + this.and = + (this.and ?: JsonField.of(mutableListOf())).also { checkKnown("and", it).add(and) } + } + + fun or(or: List>) = or(JsonField.of(or)) + + /** + * Sets [Builder.or] to an arbitrary JSON value. + * + * You should usually call [Builder.or] with a well-typed `List>` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun or(or: JsonField>>) = apply { + this.or = or.map { it.toMutableList() } + } + + /** + * Adds a single [List] to [Builder.or]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addOr(or: List) = apply { + this.or = + (this.or ?: JsonField.of(mutableListOf())).also { checkKnown("or", it).add(or) } + } + + 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 [JourneyConditionGroup]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyConditionGroup = + JourneyConditionGroup( + (and ?: JsonMissing.of()).map { it.toImmutable() }, + (or ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyConditionGroup = apply { + if (validated) { + return@apply + } + + and() + or() + 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 = + (and.asKnown().getOrNull()?.sumOf { it.size.toInt() } ?: 0) + + (or.asKnown().getOrNull()?.sumOf { it.size.toInt() } ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyConditionGroup && + and == other.and && + or == other.or && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(and, or, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyConditionGroup{and=$and, or=$or, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionNestedGroup.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionNestedGroup.kt new file mode 100644 index 00000000..9c59e407 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionNestedGroup.kt @@ -0,0 +1,236 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * A nested condition group. Exactly one of `AND` or `OR` must be present at runtime; each is a list + * of `JourneyConditionGroup` items. + */ +class JourneyConditionNestedGroup +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val and: JsonField>, + private val or: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("AND") + @ExcludeMissing + and: JsonField> = JsonMissing.of(), + @JsonProperty("OR") + @ExcludeMissing + or: JsonField> = JsonMissing.of(), + ) : this(and, or, mutableMapOf()) + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun and(): Optional> = and.getOptional("AND") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun or(): Optional> = or.getOptional("OR") + + /** + * Returns the raw JSON value of [and]. + * + * Unlike [and], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("AND") @ExcludeMissing fun _and(): JsonField> = and + + /** + * Returns the raw JSON value of [or]. + * + * Unlike [or], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("OR") @ExcludeMissing fun _or(): JsonField> = or + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyConditionNestedGroup]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyConditionNestedGroup]. */ + class Builder internal constructor() { + + private var and: JsonField>? = null + private var or: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyConditionNestedGroup: JourneyConditionNestedGroup) = apply { + and = journeyConditionNestedGroup.and.map { it.toMutableList() } + or = journeyConditionNestedGroup.or.map { it.toMutableList() } + additionalProperties = journeyConditionNestedGroup.additionalProperties.toMutableMap() + } + + fun and(and: List) = and(JsonField.of(and)) + + /** + * Sets [Builder.and] to an arbitrary JSON value. + * + * You should usually call [Builder.and] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun and(and: JsonField>) = apply { + this.and = and.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyConditionGroup] to [Builder.and]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addAnd(and: JourneyConditionGroup) = apply { + this.and = + (this.and ?: JsonField.of(mutableListOf())).also { checkKnown("and", it).add(and) } + } + + fun or(or: List) = or(JsonField.of(or)) + + /** + * Sets [Builder.or] to an arbitrary JSON value. + * + * You should usually call [Builder.or] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun or(or: JsonField>) = apply { + this.or = or.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyConditionGroup] to [Builder.or]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addOr(or: JourneyConditionGroup) = apply { + this.or = + (this.or ?: JsonField.of(mutableListOf())).also { checkKnown("or", it).add(or) } + } + + 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 [JourneyConditionNestedGroup]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyConditionNestedGroup = + JourneyConditionNestedGroup( + (and ?: JsonMissing.of()).map { it.toImmutable() }, + (or ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyConditionNestedGroup = apply { + if (validated) { + return@apply + } + + and().ifPresent { it.forEach { it.validate() } } + or().ifPresent { it.forEach { it.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 = + (and.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (or.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyConditionNestedGroup && + and == other.and && + or == other.or && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(and, or, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyConditionNestedGroup{and=$and, or=$or, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionsField.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionsField.kt new file mode 100644 index 00000000..7531b0f5 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyConditionsField.kt @@ -0,0 +1,374 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.BaseDeserializer +import com.courier.core.BaseSerializer +import com.courier.core.JsonValue +import com.courier.core.allMaxBy +import com.courier.core.getOrThrow +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import java.util.Objects +import java.util.Optional + +/** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an AND/OR + * nested group. Omit the `conditions` property entirely to express "no conditions". + */ +@JsonDeserialize(using = JourneyConditionsField.Deserializer::class) +@JsonSerialize(using = JourneyConditionsField.Serializer::class) +class JourneyConditionsField +private constructor( + private val conditionAtom: List? = null, + private val conditionGroup: JourneyConditionGroup? = null, + private val conditionNestedGroup: JourneyConditionNestedGroup? = null, + private val _json: JsonValue? = null, +) { + + /** + * A single condition expressed as a positional tuple of strings. + * - Binary form (3 elements): `[path, operator, value]` where `operator` is one of `is equal`, + * `is not equal`, `contains`, `does not contain`, `starts with`, `ends with`, `greater than`, + * `greater than or equal`, `less than`, `less than or equal`. + * + * Example: `["user.tier", "is equal", "gold"]`. + * - Unary form (2 elements): `[path, operator]` where `operator` is one of `exists`, `does not + * exist`. + * + * Example: `["user.email", "exists"]`. + * + * The first element is a non-empty dot-path. The second element is the operator (must come from + * one of the two operator sets above). For the binary form, the third element is the comparison + * value (string). Runtime validation of the operator value and arity is performed by the + * backend; SDKs surface this as a string list. + */ + fun conditionAtom(): Optional> = Optional.ofNullable(conditionAtom) + + /** + * A leaf condition group. Exactly one of `AND` or `OR` must be present at runtime; each is a + * list of `JourneyConditionAtom` tuples. + */ + fun conditionGroup(): Optional = Optional.ofNullable(conditionGroup) + + /** + * A nested condition group. Exactly one of `AND` or `OR` must be present at runtime; each is a + * list of `JourneyConditionGroup` items. + */ + fun conditionNestedGroup(): Optional = + Optional.ofNullable(conditionNestedGroup) + + fun isConditionAtom(): Boolean = conditionAtom != null + + fun isConditionGroup(): Boolean = conditionGroup != null + + fun isConditionNestedGroup(): Boolean = conditionNestedGroup != null + + /** + * A single condition expressed as a positional tuple of strings. + * - Binary form (3 elements): `[path, operator, value]` where `operator` is one of `is equal`, + * `is not equal`, `contains`, `does not contain`, `starts with`, `ends with`, `greater than`, + * `greater than or equal`, `less than`, `less than or equal`. + * + * Example: `["user.tier", "is equal", "gold"]`. + * - Unary form (2 elements): `[path, operator]` where `operator` is one of `exists`, `does not + * exist`. + * + * Example: `["user.email", "exists"]`. + * + * The first element is a non-empty dot-path. The second element is the operator (must come from + * one of the two operator sets above). For the binary form, the third element is the comparison + * value (string). Runtime validation of the operator value and arity is performed by the + * backend; SDKs surface this as a string list. + */ + fun asConditionAtom(): List = conditionAtom.getOrThrow("conditionAtom") + + /** + * A leaf condition group. Exactly one of `AND` or `OR` must be present at runtime; each is a + * list of `JourneyConditionAtom` tuples. + */ + fun asConditionGroup(): JourneyConditionGroup = conditionGroup.getOrThrow("conditionGroup") + + /** + * A nested condition group. Exactly one of `AND` or `OR` must be present at runtime; each is a + * list of `JourneyConditionGroup` items. + */ + fun asConditionNestedGroup(): JourneyConditionNestedGroup = + conditionNestedGroup.getOrThrow("conditionNestedGroup") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = journeyConditionsField.accept(new JourneyConditionsField.Visitor>() { + * @Override + * public Optional visitConditionAtom(List conditionAtom) { + * return Optional.of(conditionAtom.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + conditionAtom != null -> visitor.visitConditionAtom(conditionAtom) + conditionGroup != null -> visitor.visitConditionGroup(conditionGroup) + conditionNestedGroup != null -> visitor.visitConditionNestedGroup(conditionNestedGroup) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyConditionsField = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitConditionAtom(conditionAtom: List) {} + + override fun visitConditionGroup(conditionGroup: JourneyConditionGroup) { + conditionGroup.validate() + } + + override fun visitConditionNestedGroup( + conditionNestedGroup: JourneyConditionNestedGroup + ) { + conditionNestedGroup.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 visitConditionAtom(conditionAtom: List) = conditionAtom.size + + override fun visitConditionGroup(conditionGroup: JourneyConditionGroup) = + conditionGroup.validity() + + override fun visitConditionNestedGroup( + conditionNestedGroup: JourneyConditionNestedGroup + ) = conditionNestedGroup.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyConditionsField && + conditionAtom == other.conditionAtom && + conditionGroup == other.conditionGroup && + conditionNestedGroup == other.conditionNestedGroup + } + + override fun hashCode(): Int = Objects.hash(conditionAtom, conditionGroup, conditionNestedGroup) + + override fun toString(): String = + when { + conditionAtom != null -> "JourneyConditionsField{conditionAtom=$conditionAtom}" + conditionGroup != null -> "JourneyConditionsField{conditionGroup=$conditionGroup}" + conditionNestedGroup != null -> + "JourneyConditionsField{conditionNestedGroup=$conditionNestedGroup}" + _json != null -> "JourneyConditionsField{_unknown=$_json}" + else -> throw IllegalStateException("Invalid JourneyConditionsField") + } + + companion object { + + /** + * A single condition expressed as a positional tuple of strings. + * - Binary form (3 elements): `[path, operator, value]` where `operator` is one of `is + * equal`, `is not equal`, `contains`, `does not contain`, `starts with`, `ends with`, + * `greater than`, `greater than or equal`, `less than`, `less than or equal`. + * + * Example: `["user.tier", "is equal", "gold"]`. + * - Unary form (2 elements): `[path, operator]` where `operator` is one of `exists`, `does + * not exist`. + * + * Example: `["user.email", "exists"]`. + * + * The first element is a non-empty dot-path. The second element is the operator (must come + * from one of the two operator sets above). For the binary form, the third element is the + * comparison value (string). Runtime validation of the operator value and arity is + * performed by the backend; SDKs surface this as a string list. + */ + @JvmStatic + fun ofConditionAtom(conditionAtom: List) = + JourneyConditionsField(conditionAtom = conditionAtom.toImmutable()) + + /** + * A leaf condition group. Exactly one of `AND` or `OR` must be present at runtime; each is + * a list of `JourneyConditionAtom` tuples. + */ + @JvmStatic + fun ofConditionGroup(conditionGroup: JourneyConditionGroup) = + JourneyConditionsField(conditionGroup = conditionGroup) + + /** + * A nested condition group. Exactly one of `AND` or `OR` must be present at runtime; each + * is a list of `JourneyConditionGroup` items. + */ + @JvmStatic + fun ofConditionNestedGroup(conditionNestedGroup: JourneyConditionNestedGroup) = + JourneyConditionsField(conditionNestedGroup = conditionNestedGroup) + } + + /** + * An interface that defines how to map each variant of [JourneyConditionsField] to a value of + * type [T]. + */ + interface Visitor { + + /** + * A single condition expressed as a positional tuple of strings. + * - Binary form (3 elements): `[path, operator, value]` where `operator` is one of `is + * equal`, `is not equal`, `contains`, `does not contain`, `starts with`, `ends with`, + * `greater than`, `greater than or equal`, `less than`, `less than or equal`. + * + * Example: `["user.tier", "is equal", "gold"]`. + * - Unary form (2 elements): `[path, operator]` where `operator` is one of `exists`, `does + * not exist`. + * + * Example: `["user.email", "exists"]`. + * + * The first element is a non-empty dot-path. The second element is the operator (must come + * from one of the two operator sets above). For the binary form, the third element is the + * comparison value (string). Runtime validation of the operator value and arity is + * performed by the backend; SDKs surface this as a string list. + */ + fun visitConditionAtom(conditionAtom: List): T + + /** + * A leaf condition group. Exactly one of `AND` or `OR` must be present at runtime; each is + * a list of `JourneyConditionAtom` tuples. + */ + fun visitConditionGroup(conditionGroup: JourneyConditionGroup): T + + /** + * A nested condition group. Exactly one of `AND` or `OR` must be present at runtime; each + * is a list of `JourneyConditionGroup` items. + */ + fun visitConditionNestedGroup(conditionNestedGroup: JourneyConditionNestedGroup): T + + /** + * Maps an unknown variant of [JourneyConditionsField] to a value of type [T]. + * + * An instance of [JourneyConditionsField] 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 JourneyConditionsField: $json") + } + } + + internal class Deserializer : + BaseDeserializer(JourneyConditionsField::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): JourneyConditionsField { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyConditionsField(conditionGroup = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyConditionsField(conditionNestedGroup = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef>())?.let { + JourneyConditionsField(conditionAtom = 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 -> JourneyConditionsField(_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(JourneyConditionsField::class) { + + override fun serialize( + value: JourneyConditionsField, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.conditionAtom != null -> generator.writeObject(value.conditionAtom) + value.conditionGroup != null -> generator.writeObject(value.conditionGroup) + value.conditionNestedGroup != null -> + generator.writeObject(value.conditionNestedGroup) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid JourneyConditionsField") + } + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCreateParams.kt new file mode 100644 index 00000000..abe3e382 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyCreateParams.kt @@ -0,0 +1,212 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects + +/** + * Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"` to publish on create. Send + * nodes are not allowed on `POST`. The standard flow is: create the journey shell here, add + * notification templates with `POST /journeys/{templateId}/templates`, then wire them into the + * journey with `PUT /journeys/{templateId}`. Call `POST /journeys/{templateId}/publish` to publish + * a draft after the fact. + */ +class JourneyCreateParams +private constructor( + private val createJourneyRequest: CreateJourneyRequest, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Request body for creating a journey. */ + fun createJourneyRequest(): CreateJourneyRequest = createJourneyRequest + + fun _additionalBodyProperties(): Map = + createJourneyRequest._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyCreateParams]. + * + * The following fields are required: + * ```java + * .createJourneyRequest() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyCreateParams]. */ + class Builder internal constructor() { + + private var createJourneyRequest: CreateJourneyRequest? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(journeyCreateParams: JourneyCreateParams) = apply { + createJourneyRequest = journeyCreateParams.createJourneyRequest + additionalHeaders = journeyCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = journeyCreateParams.additionalQueryParams.toBuilder() + } + + /** Request body for creating a journey. */ + fun createJourneyRequest(createJourneyRequest: CreateJourneyRequest) = apply { + this.createJourneyRequest = createJourneyRequest + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [JourneyCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .createJourneyRequest() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyCreateParams = + JourneyCreateParams( + checkRequired("createJourneyRequest", createJourneyRequest), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): CreateJourneyRequest = createJourneyRequest + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyCreateParams && + createJourneyRequest == other.createJourneyRequest && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(createJourneyRequest, additionalHeaders, additionalQueryParams) + + override fun toString() = + "JourneyCreateParams{createJourneyRequest=$createJourneyRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyDelayDurationNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyDelayDurationNode.kt new file mode 100644 index 00000000..2879ddf4 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyDelayDurationNode.kt @@ -0,0 +1,606 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Pause the journey run for a fixed `duration`. */ +class JourneyDelayDurationNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val duration: JsonField, + private val mode: JsonField, + private val type: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("duration") @ExcludeMissing duration: JsonField = JsonMissing.of(), + @JsonProperty("mode") @ExcludeMissing mode: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + ) : this(duration, mode, type, id, conditions, 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). + */ + fun duration(): String = duration.getRequired("duration") + + /** + * @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 mode(): Mode = mode.getRequired("mode") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * Returns the raw JSON value of [duration]. + * + * Unlike [duration], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("duration") @ExcludeMissing fun _duration(): JsonField = duration + + /** + * Returns the raw JSON value of [mode]. + * + * Unlike [mode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("mode") @ExcludeMissing fun _mode(): JsonField = mode + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyDelayDurationNode]. + * + * The following fields are required: + * ```java + * .duration() + * .mode() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyDelayDurationNode]. */ + class Builder internal constructor() { + + private var duration: JsonField? = null + private var mode: JsonField? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyDelayDurationNode: JourneyDelayDurationNode) = apply { + duration = journeyDelayDurationNode.duration + mode = journeyDelayDurationNode.mode + type = journeyDelayDurationNode.type + id = journeyDelayDurationNode.id + conditions = journeyDelayDurationNode.conditions + additionalProperties = journeyDelayDurationNode.additionalProperties.toMutableMap() + } + + fun duration(duration: String) = duration(JsonField.of(duration)) + + /** + * Sets [Builder.duration] to an arbitrary JSON value. + * + * You should usually call [Builder.duration] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun duration(duration: JsonField) = apply { this.duration = duration } + + fun mode(mode: Mode) = mode(JsonField.of(mode)) + + /** + * Sets [Builder.mode] to an arbitrary JSON value. + * + * You should usually call [Builder.mode] with a well-typed [Mode] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun mode(mode: JsonField) = apply { this.mode = mode } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + 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 [JourneyDelayDurationNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .duration() + * .mode() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyDelayDurationNode = + JourneyDelayDurationNode( + checkRequired("duration", duration), + checkRequired("mode", mode), + checkRequired("type", type), + id, + conditions, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyDelayDurationNode = apply { + if (validated) { + return@apply + } + + duration() + mode().validate() + type().validate() + id() + conditions().ifPresent { it.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 = + (if (duration.asKnown().isPresent) 1 else 0) + + (mode.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + class Mode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DURATION = of("duration") + + @JvmStatic fun of(value: String) = Mode(JsonField.of(value)) + } + + /** An enum containing [Mode]'s known values. */ + enum class Known { + DURATION + } + + /** + * An enum containing [Mode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Mode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DURATION, + /** An enum member indicating that [Mode] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DURATION -> Value.DURATION + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + DURATION -> Known.DURATION + else -> throw CourierInvalidDataException("Unknown Mode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Mode = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Mode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DELAY = of("delay") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + DELAY + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DELAY, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DELAY -> Value.DELAY + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + DELAY -> Known.DELAY + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyDelayDurationNode && + duration == other.duration && + mode == other.mode && + type == other.type && + id == other.id && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(duration, mode, type, id, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyDelayDurationNode{duration=$duration, mode=$mode, type=$type, id=$id, conditions=$conditions, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyDelayUntilNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyDelayUntilNode.kt new file mode 100644 index 00000000..8e7c63c3 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyDelayUntilNode.kt @@ -0,0 +1,606 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Pause the journey run `until` a specific time. */ +class JourneyDelayUntilNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val mode: JsonField, + private val type: JsonField, + private val until: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("mode") @ExcludeMissing mode: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("until") @ExcludeMissing until: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + ) : this(mode, type, until, id, conditions, 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). + */ + fun mode(): Mode = mode.getRequired("mode") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @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 until(): String = until.getRequired("until") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * Returns the raw JSON value of [mode]. + * + * Unlike [mode], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("mode") @ExcludeMissing fun _mode(): JsonField = mode + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [until]. + * + * Unlike [until], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("until") @ExcludeMissing fun _until(): JsonField = until + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyDelayUntilNode]. + * + * The following fields are required: + * ```java + * .mode() + * .type() + * .until() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyDelayUntilNode]. */ + class Builder internal constructor() { + + private var mode: JsonField? = null + private var type: JsonField? = null + private var until: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyDelayUntilNode: JourneyDelayUntilNode) = apply { + mode = journeyDelayUntilNode.mode + type = journeyDelayUntilNode.type + until = journeyDelayUntilNode.until + id = journeyDelayUntilNode.id + conditions = journeyDelayUntilNode.conditions + additionalProperties = journeyDelayUntilNode.additionalProperties.toMutableMap() + } + + fun mode(mode: Mode) = mode(JsonField.of(mode)) + + /** + * Sets [Builder.mode] to an arbitrary JSON value. + * + * You should usually call [Builder.mode] with a well-typed [Mode] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun mode(mode: JsonField) = apply { this.mode = mode } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun until(until: String) = until(JsonField.of(until)) + + /** + * Sets [Builder.until] to an arbitrary JSON value. + * + * You should usually call [Builder.until] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun until(until: JsonField) = apply { this.until = until } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + 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 [JourneyDelayUntilNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .mode() + * .type() + * .until() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyDelayUntilNode = + JourneyDelayUntilNode( + checkRequired("mode", mode), + checkRequired("type", type), + checkRequired("until", until), + id, + conditions, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyDelayUntilNode = apply { + if (validated) { + return@apply + } + + mode().validate() + type().validate() + until() + id() + conditions().ifPresent { it.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 = + (mode.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (until.asKnown().isPresent) 1 else 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + class Mode @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val UNTIL = of("until") + + @JvmStatic fun of(value: String) = Mode(JsonField.of(value)) + } + + /** An enum containing [Mode]'s known values. */ + enum class Known { + UNTIL + } + + /** + * An enum containing [Mode]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Mode] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + UNTIL, + /** An enum member indicating that [Mode] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + UNTIL -> Value.UNTIL + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + UNTIL -> Known.UNTIL + else -> throw CourierInvalidDataException("Unknown Mode: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Mode = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Mode && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DELAY = of("delay") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + DELAY + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DELAY, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DELAY -> Value.DELAY + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + DELAY -> Known.DELAY + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyDelayUntilNode && + mode == other.mode && + type == other.type && + until == other.until && + id == other.id && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(mode, type, until, id, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyDelayUntilNode{mode=$mode, type=$type, until=$until, id=$id, conditions=$conditions, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyExitNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyExitNode.kt new file mode 100644 index 00000000..f25c1b6d --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyExitNode.kt @@ -0,0 +1,338 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Terminate the journey run. */ +class JourneyExitNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val type: JsonField, + private val id: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + ) : this(type, id, 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). + */ + fun type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyExitNode]. + * + * The following fields are required: + * ```java + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyExitNode]. */ + class Builder internal constructor() { + + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyExitNode: JourneyExitNode) = apply { + type = journeyExitNode.type + id = journeyExitNode.id + additionalProperties = journeyExitNode.additionalProperties.toMutableMap() + } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + 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 [JourneyExitNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyExitNode = + JourneyExitNode(checkRequired("type", type), id, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyExitNode = apply { + if (validated) { + return@apply + } + + type().validate() + id() + 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 = + (type.asKnown().getOrNull()?.validity() ?: 0) + (if (id.asKnown().isPresent) 1 else 0) + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val EXIT = of("exit") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + EXIT + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + EXIT, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + EXIT -> Value.EXIT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + EXIT -> Known.EXIT + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyExitNode && + type == other.type && + id == other.id && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(type, id, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyExitNode{type=$type, id=$id, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyFetchGetDeleteNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyFetchGetDeleteNode.kt new file mode 100644 index 00000000..34b0b33a --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyFetchGetDeleteNode.kt @@ -0,0 +1,1118 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Issue an HTTP GET or DELETE request and merge the response into the journey state per + * `merge_strategy`. + */ +class JourneyFetchGetDeleteNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val mergeStrategy: JsonField, + private val method: JsonField, + private val type: JsonField, + private val url: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val headers: JsonField, + private val queryParams: JsonField, + private val responseSchema: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("merge_strategy") + @ExcludeMissing + mergeStrategy: JsonField = JsonMissing.of(), + @JsonProperty("method") @ExcludeMissing method: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + @JsonProperty("headers") @ExcludeMissing headers: JsonField = JsonMissing.of(), + @JsonProperty("query_params") + @ExcludeMissing + queryParams: JsonField = JsonMissing.of(), + @JsonProperty("response_schema") + @ExcludeMissing + responseSchema: JsonField = JsonMissing.of(), + ) : this( + mergeStrategy, + method, + type, + url, + id, + conditions, + headers, + queryParams, + responseSchema, + mutableMapOf(), + ) + + /** + * Strategy for merging a fetch response into the journey run state. + * + * @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 mergeStrategy(): JourneyMergeStrategy = mergeStrategy.getRequired("merge_strategy") + + /** + * @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 method(): Method = method.getRequired("method") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @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 url(): String = url.getRequired("url") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun headers(): Optional = headers.getOptional("headers") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun queryParams(): Optional = queryParams.getOptional("query_params") + + /** + * A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun responseSchema(): Optional = responseSchema.getOptional("response_schema") + + /** + * Returns the raw JSON value of [mergeStrategy]. + * + * Unlike [mergeStrategy], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("merge_strategy") + @ExcludeMissing + fun _mergeStrategy(): JsonField = mergeStrategy + + /** + * Returns the raw JSON value of [method]. + * + * Unlike [method], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [url]. + * + * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + /** + * Returns the raw JSON value of [headers]. + * + * Unlike [headers], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("headers") @ExcludeMissing fun _headers(): JsonField = headers + + /** + * Returns the raw JSON value of [queryParams]. + * + * Unlike [queryParams], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("query_params") + @ExcludeMissing + fun _queryParams(): JsonField = queryParams + + /** + * Returns the raw JSON value of [responseSchema]. + * + * Unlike [responseSchema], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("response_schema") + @ExcludeMissing + fun _responseSchema(): JsonField = responseSchema + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyFetchGetDeleteNode]. + * + * The following fields are required: + * ```java + * .mergeStrategy() + * .method() + * .type() + * .url() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyFetchGetDeleteNode]. */ + class Builder internal constructor() { + + private var mergeStrategy: JsonField? = null + private var method: JsonField? = null + private var type: JsonField? = null + private var url: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var headers: JsonField = JsonMissing.of() + private var queryParams: JsonField = JsonMissing.of() + private var responseSchema: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyFetchGetDeleteNode: JourneyFetchGetDeleteNode) = apply { + mergeStrategy = journeyFetchGetDeleteNode.mergeStrategy + method = journeyFetchGetDeleteNode.method + type = journeyFetchGetDeleteNode.type + url = journeyFetchGetDeleteNode.url + id = journeyFetchGetDeleteNode.id + conditions = journeyFetchGetDeleteNode.conditions + headers = journeyFetchGetDeleteNode.headers + queryParams = journeyFetchGetDeleteNode.queryParams + responseSchema = journeyFetchGetDeleteNode.responseSchema + additionalProperties = journeyFetchGetDeleteNode.additionalProperties.toMutableMap() + } + + /** Strategy for merging a fetch response into the journey run state. */ + fun mergeStrategy(mergeStrategy: JourneyMergeStrategy) = + mergeStrategy(JsonField.of(mergeStrategy)) + + /** + * Sets [Builder.mergeStrategy] to an arbitrary JSON value. + * + * You should usually call [Builder.mergeStrategy] with a well-typed [JourneyMergeStrategy] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun mergeStrategy(mergeStrategy: JsonField) = apply { + this.mergeStrategy = mergeStrategy + } + + fun method(method: Method) = method(JsonField.of(method)) + + /** + * Sets [Builder.method] to an arbitrary JSON value. + * + * You should usually call [Builder.method] with a well-typed [Method] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun method(method: JsonField) = apply { this.method = method } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun url(url: String) = url(JsonField.of(url)) + + /** + * Sets [Builder.url] to an arbitrary JSON value. + * + * You should usually call [Builder.url] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun url(url: JsonField) = apply { this.url = url } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + fun headers(headers: Headers) = headers(JsonField.of(headers)) + + /** + * Sets [Builder.headers] to an arbitrary JSON value. + * + * You should usually call [Builder.headers] with a well-typed [Headers] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun headers(headers: JsonField) = apply { this.headers = headers } + + fun queryParams(queryParams: QueryParams) = queryParams(JsonField.of(queryParams)) + + /** + * Sets [Builder.queryParams] to an arbitrary JSON value. + * + * You should usually call [Builder.queryParams] with a well-typed [QueryParams] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun queryParams(queryParams: JsonField) = apply { + this.queryParams = queryParams + } + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + fun responseSchema(responseSchema: ResponseSchema) = + responseSchema(JsonField.of(responseSchema)) + + /** + * Sets [Builder.responseSchema] to an arbitrary JSON value. + * + * You should usually call [Builder.responseSchema] with a well-typed [ResponseSchema] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun responseSchema(responseSchema: JsonField) = apply { + this.responseSchema = responseSchema + } + + 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 [JourneyFetchGetDeleteNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .mergeStrategy() + * .method() + * .type() + * .url() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyFetchGetDeleteNode = + JourneyFetchGetDeleteNode( + checkRequired("mergeStrategy", mergeStrategy), + checkRequired("method", method), + checkRequired("type", type), + checkRequired("url", url), + id, + conditions, + headers, + queryParams, + responseSchema, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyFetchGetDeleteNode = apply { + if (validated) { + return@apply + } + + mergeStrategy().validate() + method().validate() + type().validate() + url() + id() + conditions().ifPresent { it.validate() } + headers().ifPresent { it.validate() } + queryParams().ifPresent { it.validate() } + responseSchema().ifPresent { it.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 = + (mergeStrategy.asKnown().getOrNull()?.validity() ?: 0) + + (method.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (url.asKnown().isPresent) 1 else 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + (headers.asKnown().getOrNull()?.validity() ?: 0) + + (queryParams.asKnown().getOrNull()?.validity() ?: 0) + + (responseSchema.asKnown().getOrNull()?.validity() ?: 0) + + class Method @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val GET = of("get") + + @JvmField val DELETE = of("delete") + + @JvmStatic fun of(value: String) = Method(JsonField.of(value)) + } + + /** An enum containing [Method]'s known values. */ + enum class Known { + GET, + DELETE, + } + + /** + * An enum containing [Method]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Method] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + GET, + DELETE, + /** An enum member indicating that [Method] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + GET -> Value.GET + DELETE -> Value.DELETE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + GET -> Known.GET + DELETE -> Known.DELETE + else -> throw CourierInvalidDataException("Unknown Method: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Method = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Method && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val FETCH = of("fetch") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + FETCH + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + FETCH, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + FETCH -> Value.FETCH + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + FETCH -> Known.FETCH + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Headers + @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 [Headers]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Headers]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(headers: Headers) = apply { + additionalProperties = headers.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 [Headers]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Headers = Headers(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Headers = 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 Headers && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Headers{additionalProperties=$additionalProperties}" + } + + class QueryParams + @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 [QueryParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [QueryParams]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(queryParams: QueryParams) = apply { + additionalProperties = queryParams.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 [QueryParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): QueryParams = QueryParams(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): QueryParams = 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 QueryParams && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "QueryParams{additionalProperties=$additionalProperties}" + } + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + class ResponseSchema + @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 [ResponseSchema]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ResponseSchema]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(responseSchema: ResponseSchema) = apply { + additionalProperties = responseSchema.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 [ResponseSchema]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ResponseSchema = ResponseSchema(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): ResponseSchema = 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 ResponseSchema && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "ResponseSchema{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyFetchGetDeleteNode && + mergeStrategy == other.mergeStrategy && + method == other.method && + type == other.type && + url == other.url && + id == other.id && + conditions == other.conditions && + headers == other.headers && + queryParams == other.queryParams && + responseSchema == other.responseSchema && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + mergeStrategy, + method, + type, + url, + id, + conditions, + headers, + queryParams, + responseSchema, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyFetchGetDeleteNode{mergeStrategy=$mergeStrategy, method=$method, type=$type, url=$url, id=$id, conditions=$conditions, headers=$headers, queryParams=$queryParams, responseSchema=$responseSchema, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyFetchPostPutNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyFetchPostPutNode.kt new file mode 100644 index 00000000..d96a71a1 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyFetchPostPutNode.kt @@ -0,0 +1,1151 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Issue an HTTP POST or PUT request with a `body` and merge the response into the journey state per + * `merge_strategy`. + */ +class JourneyFetchPostPutNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val mergeStrategy: JsonField, + private val method: JsonField, + private val type: JsonField, + private val url: JsonField, + private val id: JsonField, + private val body: JsonField, + private val conditions: JsonField, + private val headers: JsonField, + private val queryParams: JsonField, + private val responseSchema: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("merge_strategy") + @ExcludeMissing + mergeStrategy: JsonField = JsonMissing.of(), + @JsonProperty("method") @ExcludeMissing method: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("body") @ExcludeMissing body: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + @JsonProperty("headers") @ExcludeMissing headers: JsonField = JsonMissing.of(), + @JsonProperty("query_params") + @ExcludeMissing + queryParams: JsonField = JsonMissing.of(), + @JsonProperty("response_schema") + @ExcludeMissing + responseSchema: JsonField = JsonMissing.of(), + ) : this( + mergeStrategy, + method, + type, + url, + id, + body, + conditions, + headers, + queryParams, + responseSchema, + mutableMapOf(), + ) + + /** + * Strategy for merging a fetch response into the journey run state. + * + * @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 mergeStrategy(): JourneyMergeStrategy = mergeStrategy.getRequired("merge_strategy") + + /** + * @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 method(): Method = method.getRequired("method") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @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 url(): String = url.getRequired("url") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun body(): Optional = body.getOptional("body") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun headers(): Optional = headers.getOptional("headers") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun queryParams(): Optional = queryParams.getOptional("query_params") + + /** + * A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun responseSchema(): Optional = responseSchema.getOptional("response_schema") + + /** + * Returns the raw JSON value of [mergeStrategy]. + * + * Unlike [mergeStrategy], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("merge_strategy") + @ExcludeMissing + fun _mergeStrategy(): JsonField = mergeStrategy + + /** + * Returns the raw JSON value of [method]. + * + * Unlike [method], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("method") @ExcludeMissing fun _method(): JsonField = method + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [url]. + * + * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [body]. + * + * Unlike [body], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("body") @ExcludeMissing fun _body(): JsonField = body + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + /** + * Returns the raw JSON value of [headers]. + * + * Unlike [headers], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("headers") @ExcludeMissing fun _headers(): JsonField = headers + + /** + * Returns the raw JSON value of [queryParams]. + * + * Unlike [queryParams], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("query_params") + @ExcludeMissing + fun _queryParams(): JsonField = queryParams + + /** + * Returns the raw JSON value of [responseSchema]. + * + * Unlike [responseSchema], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("response_schema") + @ExcludeMissing + fun _responseSchema(): JsonField = responseSchema + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyFetchPostPutNode]. + * + * The following fields are required: + * ```java + * .mergeStrategy() + * .method() + * .type() + * .url() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyFetchPostPutNode]. */ + class Builder internal constructor() { + + private var mergeStrategy: JsonField? = null + private var method: JsonField? = null + private var type: JsonField? = null + private var url: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var body: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var headers: JsonField = JsonMissing.of() + private var queryParams: JsonField = JsonMissing.of() + private var responseSchema: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyFetchPostPutNode: JourneyFetchPostPutNode) = apply { + mergeStrategy = journeyFetchPostPutNode.mergeStrategy + method = journeyFetchPostPutNode.method + type = journeyFetchPostPutNode.type + url = journeyFetchPostPutNode.url + id = journeyFetchPostPutNode.id + body = journeyFetchPostPutNode.body + conditions = journeyFetchPostPutNode.conditions + headers = journeyFetchPostPutNode.headers + queryParams = journeyFetchPostPutNode.queryParams + responseSchema = journeyFetchPostPutNode.responseSchema + additionalProperties = journeyFetchPostPutNode.additionalProperties.toMutableMap() + } + + /** Strategy for merging a fetch response into the journey run state. */ + fun mergeStrategy(mergeStrategy: JourneyMergeStrategy) = + mergeStrategy(JsonField.of(mergeStrategy)) + + /** + * Sets [Builder.mergeStrategy] to an arbitrary JSON value. + * + * You should usually call [Builder.mergeStrategy] with a well-typed [JourneyMergeStrategy] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun mergeStrategy(mergeStrategy: JsonField) = apply { + this.mergeStrategy = mergeStrategy + } + + fun method(method: Method) = method(JsonField.of(method)) + + /** + * Sets [Builder.method] to an arbitrary JSON value. + * + * You should usually call [Builder.method] with a well-typed [Method] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun method(method: JsonField) = apply { this.method = method } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun url(url: String) = url(JsonField.of(url)) + + /** + * Sets [Builder.url] to an arbitrary JSON value. + * + * You should usually call [Builder.url] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun url(url: JsonField) = apply { this.url = url } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun body(body: String) = body(JsonField.of(body)) + + /** + * Sets [Builder.body] to an arbitrary JSON value. + * + * You should usually call [Builder.body] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun body(body: JsonField) = apply { this.body = body } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + fun headers(headers: Headers) = headers(JsonField.of(headers)) + + /** + * Sets [Builder.headers] to an arbitrary JSON value. + * + * You should usually call [Builder.headers] with a well-typed [Headers] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun headers(headers: JsonField) = apply { this.headers = headers } + + fun queryParams(queryParams: QueryParams) = queryParams(JsonField.of(queryParams)) + + /** + * Sets [Builder.queryParams] to an arbitrary JSON value. + * + * You should usually call [Builder.queryParams] with a well-typed [QueryParams] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun queryParams(queryParams: JsonField) = apply { + this.queryParams = queryParams + } + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + fun responseSchema(responseSchema: ResponseSchema) = + responseSchema(JsonField.of(responseSchema)) + + /** + * Sets [Builder.responseSchema] to an arbitrary JSON value. + * + * You should usually call [Builder.responseSchema] with a well-typed [ResponseSchema] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun responseSchema(responseSchema: JsonField) = apply { + this.responseSchema = responseSchema + } + + 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 [JourneyFetchPostPutNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .mergeStrategy() + * .method() + * .type() + * .url() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyFetchPostPutNode = + JourneyFetchPostPutNode( + checkRequired("mergeStrategy", mergeStrategy), + checkRequired("method", method), + checkRequired("type", type), + checkRequired("url", url), + id, + body, + conditions, + headers, + queryParams, + responseSchema, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyFetchPostPutNode = apply { + if (validated) { + return@apply + } + + mergeStrategy().validate() + method().validate() + type().validate() + url() + id() + body() + conditions().ifPresent { it.validate() } + headers().ifPresent { it.validate() } + queryParams().ifPresent { it.validate() } + responseSchema().ifPresent { it.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 = + (mergeStrategy.asKnown().getOrNull()?.validity() ?: 0) + + (method.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (url.asKnown().isPresent) 1 else 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (if (body.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + (headers.asKnown().getOrNull()?.validity() ?: 0) + + (queryParams.asKnown().getOrNull()?.validity() ?: 0) + + (responseSchema.asKnown().getOrNull()?.validity() ?: 0) + + class Method @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val POST = of("post") + + @JvmField val PUT = of("put") + + @JvmStatic fun of(value: String) = Method(JsonField.of(value)) + } + + /** An enum containing [Method]'s known values. */ + enum class Known { + POST, + PUT, + } + + /** + * An enum containing [Method]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Method] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + POST, + PUT, + /** An enum member indicating that [Method] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + POST -> Value.POST + PUT -> Value.PUT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + POST -> Known.POST + PUT -> Known.PUT + else -> throw CourierInvalidDataException("Unknown Method: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Method = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Method && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val FETCH = of("fetch") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + FETCH + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + FETCH, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + FETCH -> Value.FETCH + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + FETCH -> Known.FETCH + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Headers + @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 [Headers]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Headers]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(headers: Headers) = apply { + additionalProperties = headers.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 [Headers]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Headers = Headers(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Headers = 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 Headers && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Headers{additionalProperties=$additionalProperties}" + } + + class QueryParams + @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 [QueryParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [QueryParams]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(queryParams: QueryParams) = apply { + additionalProperties = queryParams.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 [QueryParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): QueryParams = QueryParams(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): QueryParams = 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 QueryParams && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "QueryParams{additionalProperties=$additionalProperties}" + } + + /** A JSONSchema object (Draft-07-compatible). Validated at runtime by Ajv. */ + class ResponseSchema + @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 [ResponseSchema]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [ResponseSchema]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(responseSchema: ResponseSchema) = apply { + additionalProperties = responseSchema.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 [ResponseSchema]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): ResponseSchema = ResponseSchema(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): ResponseSchema = 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 ResponseSchema && additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "ResponseSchema{additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyFetchPostPutNode && + mergeStrategy == other.mergeStrategy && + method == other.method && + type == other.type && + url == other.url && + id == other.id && + body == other.body && + conditions == other.conditions && + headers == other.headers && + queryParams == other.queryParams && + responseSchema == other.responseSchema && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + mergeStrategy, + method, + type, + url, + id, + body, + conditions, + headers, + queryParams, + responseSchema, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyFetchPostPutNode{mergeStrategy=$mergeStrategy, method=$method, type=$type, url=$url, id=$id, body=$body, conditions=$conditions, headers=$headers, queryParams=$queryParams, responseSchema=$responseSchema, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt index d4585542..817b5254 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyInvokeParams.kt @@ -11,7 +11,10 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Invoke a journey run from a journey template. */ +/** + * Invoke a journey by id or alias to start a new run. The response includes a `runId` identifying + * the run. + */ class JourneyInvokeParams private constructor( private val templateId: String?, diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt index 33c24c7c..8392863d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListParams.kt @@ -298,6 +298,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Version = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListVersionsParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListVersionsParams.kt new file mode 100644 index 00000000..5531ac06 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyListVersionsParams.kt @@ -0,0 +1,196 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** List published versions of a journey, ordered most recent first. */ +class JourneyListVersionsParams +private constructor( + private val templateId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): JourneyListVersionsParams = builder().build() + + /** + * Returns a mutable builder for constructing an instance of [JourneyListVersionsParams]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyListVersionsParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(journeyListVersionsParams: JourneyListVersionsParams) = apply { + templateId = journeyListVersionsParams.templateId + additionalHeaders = journeyListVersionsParams.additionalHeaders.toBuilder() + additionalQueryParams = journeyListVersionsParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [JourneyListVersionsParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyListVersionsParams = + JourneyListVersionsParams( + templateId, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyListVersionsParams && + templateId == other.templateId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(templateId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "JourneyListVersionsParams{templateId=$templateId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyMergeStrategy.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyMergeStrategy.kt new file mode 100644 index 00000000..e6eed01a --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyMergeStrategy.kt @@ -0,0 +1,155 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.JsonField +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonCreator + +/** Strategy for merging a fetch response into the journey run state. */ +class JourneyMergeStrategy @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't match + * any known member, and you want to know that value. For example, if the SDK is on an older + * version than the API, then the API may respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val OVERWRITE = of("overwrite") + + @JvmField val SOFT_MERGE = of("soft-merge") + + @JvmField val REPLACE = of("replace") + + @JvmField val NONE = of("none") + + @JvmStatic fun of(value: String) = JourneyMergeStrategy(JsonField.of(value)) + } + + /** An enum containing [JourneyMergeStrategy]'s known values. */ + enum class Known { + OVERWRITE, + SOFT_MERGE, + REPLACE, + NONE, + } + + /** + * An enum containing [JourneyMergeStrategy]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [JourneyMergeStrategy] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the SDK + * is on an older version than the API, then the API may respond with new members that the SDK + * is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + OVERWRITE, + SOFT_MERGE, + REPLACE, + NONE, + /** + * An enum member indicating that [JourneyMergeStrategy] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] if + * the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want to + * throw for the unknown case. + */ + fun value(): Value = + when (this) { + OVERWRITE -> Value.OVERWRITE + SOFT_MERGE -> Value.SOFT_MERGE + REPLACE -> Value.REPLACE + NONE -> Value.NONE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't want + * to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known member. + */ + fun known(): Known = + when (this) { + OVERWRITE -> Known.OVERWRITE + SOFT_MERGE -> Known.SOFT_MERGE + REPLACE -> Known.REPLACE + NONE -> Known.NONE + else -> throw CourierInvalidDataException("Unknown JourneyMergeStrategy: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging and + * generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the expected + * primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyMergeStrategy = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyMergeStrategy && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyNode.kt new file mode 100644 index 00000000..eac0dbd7 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyNode.kt @@ -0,0 +1,1726 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.BaseDeserializer +import com.courier.core.BaseSerializer +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.allMaxBy +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.getOrThrow +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * A single node in a journey DAG. Discriminated by `type`, with a secondary discriminator on some + * variants (`trigger_type` for trigger, `mode` for delay, `method` for fetch, `scope` for + * throttle). + */ +@JsonDeserialize(using = JourneyNode.Deserializer::class) +@JsonSerialize(using = JourneyNode.Serializer::class) +class JourneyNode +private constructor( + private val apiInvokeTrigger: JourneyApiInvokeTriggerNode? = null, + private val segmentTrigger: JourneySegmentTriggerNode? = null, + private val send: JourneySendNode? = null, + private val delayDuration: JourneyDelayDurationNode? = null, + private val delayUntil: JourneyDelayUntilNode? = null, + private val fetchGetDelete: JourneyFetchGetDeleteNode? = null, + private val fetchPostPut: JourneyFetchPostPutNode? = null, + private val ai: JourneyAiNode? = null, + private val throttleStatic: JourneyThrottleStaticNode? = null, + private val throttleDynamic: JourneyThrottleDynamicNode? = null, + private val exit: JourneyExitNode? = null, + private val branch: JourneyBranchNode? = null, + private val _json: JsonValue? = null, +) { + + /** + * Trigger fired when the journey is invoked via the API. The optional `schema` field is a JSON + * Schema that validates the invocation payload. + */ + fun apiInvokeTrigger(): Optional = + Optional.ofNullable(apiInvokeTrigger) + + /** Trigger fired by a segment event (`identify`, `group`, or `track`). */ + fun segmentTrigger(): Optional = Optional.ofNullable(segmentTrigger) + + /** + * Send a notification template to the recipient. Optionally override the recipient address, + * delay the send, or attach `data`. + */ + fun send(): Optional = Optional.ofNullable(send) + + /** Pause the journey run for a fixed `duration`. */ + fun delayDuration(): Optional = Optional.ofNullable(delayDuration) + + /** Pause the journey run `until` a specific time. */ + fun delayUntil(): Optional = Optional.ofNullable(delayUntil) + + /** + * Issue an HTTP GET or DELETE request and merge the response into the journey state per + * `merge_strategy`. + */ + fun fetchGetDelete(): Optional = Optional.ofNullable(fetchGetDelete) + + /** + * Issue an HTTP POST or PUT request with a `body` and merge the response into the journey state + * per `merge_strategy`. + */ + fun fetchPostPut(): Optional = Optional.ofNullable(fetchPostPut) + + /** + * Invoke an AI step with `user_prompt` and optional `web_search`. Returns a structured response + * conforming to `output_schema`. + */ + fun ai(): Optional = Optional.ofNullable(ai) + + /** + * Throttle the journey by a static `scope` (`user` or `global`), allowing at most `max_allowed` + * invocations per `period`. + */ + fun throttleStatic(): Optional = Optional.ofNullable(throttleStatic) + + /** + * Throttle the journey by a dynamic `throttle_key`, allowing at most `max_allowed` invocations + * per `period`. + */ + fun throttleDynamic(): Optional = + Optional.ofNullable(throttleDynamic) + + /** Terminate the journey run. */ + fun exit(): Optional = Optional.ofNullable(exit) + + /** + * Branch node. Routes to the first entry in `paths[]` whose `conditions` match, else falls + * through to `default.nodes`. + */ + fun branch(): Optional = Optional.ofNullable(branch) + + fun isApiInvokeTrigger(): Boolean = apiInvokeTrigger != null + + fun isSegmentTrigger(): Boolean = segmentTrigger != null + + fun isSend(): Boolean = send != null + + fun isDelayDuration(): Boolean = delayDuration != null + + fun isDelayUntil(): Boolean = delayUntil != null + + fun isFetchGetDelete(): Boolean = fetchGetDelete != null + + fun isFetchPostPut(): Boolean = fetchPostPut != null + + fun isAi(): Boolean = ai != null + + fun isThrottleStatic(): Boolean = throttleStatic != null + + fun isThrottleDynamic(): Boolean = throttleDynamic != null + + fun isExit(): Boolean = exit != null + + fun isBranch(): Boolean = branch != null + + /** + * Trigger fired when the journey is invoked via the API. The optional `schema` field is a JSON + * Schema that validates the invocation payload. + */ + fun asApiInvokeTrigger(): JourneyApiInvokeTriggerNode = + apiInvokeTrigger.getOrThrow("apiInvokeTrigger") + + /** Trigger fired by a segment event (`identify`, `group`, or `track`). */ + fun asSegmentTrigger(): JourneySegmentTriggerNode = segmentTrigger.getOrThrow("segmentTrigger") + + /** + * Send a notification template to the recipient. Optionally override the recipient address, + * delay the send, or attach `data`. + */ + fun asSend(): JourneySendNode = send.getOrThrow("send") + + /** Pause the journey run for a fixed `duration`. */ + fun asDelayDuration(): JourneyDelayDurationNode = delayDuration.getOrThrow("delayDuration") + + /** Pause the journey run `until` a specific time. */ + fun asDelayUntil(): JourneyDelayUntilNode = delayUntil.getOrThrow("delayUntil") + + /** + * Issue an HTTP GET or DELETE request and merge the response into the journey state per + * `merge_strategy`. + */ + fun asFetchGetDelete(): JourneyFetchGetDeleteNode = fetchGetDelete.getOrThrow("fetchGetDelete") + + /** + * Issue an HTTP POST or PUT request with a `body` and merge the response into the journey state + * per `merge_strategy`. + */ + fun asFetchPostPut(): JourneyFetchPostPutNode = fetchPostPut.getOrThrow("fetchPostPut") + + /** + * Invoke an AI step with `user_prompt` and optional `web_search`. Returns a structured response + * conforming to `output_schema`. + */ + fun asAi(): JourneyAiNode = ai.getOrThrow("ai") + + /** + * Throttle the journey by a static `scope` (`user` or `global`), allowing at most `max_allowed` + * invocations per `period`. + */ + fun asThrottleStatic(): JourneyThrottleStaticNode = throttleStatic.getOrThrow("throttleStatic") + + /** + * Throttle the journey by a dynamic `throttle_key`, allowing at most `max_allowed` invocations + * per `period`. + */ + fun asThrottleDynamic(): JourneyThrottleDynamicNode = + throttleDynamic.getOrThrow("throttleDynamic") + + /** Terminate the journey run. */ + fun asExit(): JourneyExitNode = exit.getOrThrow("exit") + + /** + * Branch node. Routes to the first entry in `paths[]` whose `conditions` match, else falls + * through to `default.nodes`. + */ + fun asBranch(): JourneyBranchNode = branch.getOrThrow("branch") + + fun _json(): Optional = Optional.ofNullable(_json) + + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = journeyNode.accept(new JourneyNode.Visitor>() { + * @Override + * public Optional visitApiInvokeTrigger(JourneyApiInvokeTriggerNode apiInvokeTrigger) { + * return Optional.of(apiInvokeTrigger.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ + fun accept(visitor: Visitor): T = + when { + apiInvokeTrigger != null -> visitor.visitApiInvokeTrigger(apiInvokeTrigger) + segmentTrigger != null -> visitor.visitSegmentTrigger(segmentTrigger) + send != null -> visitor.visitSend(send) + delayDuration != null -> visitor.visitDelayDuration(delayDuration) + delayUntil != null -> visitor.visitDelayUntil(delayUntil) + fetchGetDelete != null -> visitor.visitFetchGetDelete(fetchGetDelete) + fetchPostPut != null -> visitor.visitFetchPostPut(fetchPostPut) + ai != null -> visitor.visitAi(ai) + throttleStatic != null -> visitor.visitThrottleStatic(throttleStatic) + throttleDynamic != null -> visitor.visitThrottleDynamic(throttleDynamic) + exit != null -> visitor.visitExit(exit) + branch != null -> visitor.visitBranch(branch) + else -> visitor.unknown(_json) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyNode = apply { + if (validated) { + return@apply + } + + accept( + object : Visitor { + override fun visitApiInvokeTrigger(apiInvokeTrigger: JourneyApiInvokeTriggerNode) { + apiInvokeTrigger.validate() + } + + override fun visitSegmentTrigger(segmentTrigger: JourneySegmentTriggerNode) { + segmentTrigger.validate() + } + + override fun visitSend(send: JourneySendNode) { + send.validate() + } + + override fun visitDelayDuration(delayDuration: JourneyDelayDurationNode) { + delayDuration.validate() + } + + override fun visitDelayUntil(delayUntil: JourneyDelayUntilNode) { + delayUntil.validate() + } + + override fun visitFetchGetDelete(fetchGetDelete: JourneyFetchGetDeleteNode) { + fetchGetDelete.validate() + } + + override fun visitFetchPostPut(fetchPostPut: JourneyFetchPostPutNode) { + fetchPostPut.validate() + } + + override fun visitAi(ai: JourneyAiNode) { + ai.validate() + } + + override fun visitThrottleStatic(throttleStatic: JourneyThrottleStaticNode) { + throttleStatic.validate() + } + + override fun visitThrottleDynamic(throttleDynamic: JourneyThrottleDynamicNode) { + throttleDynamic.validate() + } + + override fun visitExit(exit: JourneyExitNode) { + exit.validate() + } + + override fun visitBranch(branch: JourneyBranchNode) { + branch.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 visitApiInvokeTrigger(apiInvokeTrigger: JourneyApiInvokeTriggerNode) = + apiInvokeTrigger.validity() + + override fun visitSegmentTrigger(segmentTrigger: JourneySegmentTriggerNode) = + segmentTrigger.validity() + + override fun visitSend(send: JourneySendNode) = send.validity() + + override fun visitDelayDuration(delayDuration: JourneyDelayDurationNode) = + delayDuration.validity() + + override fun visitDelayUntil(delayUntil: JourneyDelayUntilNode) = + delayUntil.validity() + + override fun visitFetchGetDelete(fetchGetDelete: JourneyFetchGetDeleteNode) = + fetchGetDelete.validity() + + override fun visitFetchPostPut(fetchPostPut: JourneyFetchPostPutNode) = + fetchPostPut.validity() + + override fun visitAi(ai: JourneyAiNode) = ai.validity() + + override fun visitThrottleStatic(throttleStatic: JourneyThrottleStaticNode) = + throttleStatic.validity() + + override fun visitThrottleDynamic(throttleDynamic: JourneyThrottleDynamicNode) = + throttleDynamic.validity() + + override fun visitExit(exit: JourneyExitNode) = exit.validity() + + override fun visitBranch(branch: JourneyBranchNode) = branch.validity() + + override fun unknown(json: JsonValue?) = 0 + } + ) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyNode && + apiInvokeTrigger == other.apiInvokeTrigger && + segmentTrigger == other.segmentTrigger && + send == other.send && + delayDuration == other.delayDuration && + delayUntil == other.delayUntil && + fetchGetDelete == other.fetchGetDelete && + fetchPostPut == other.fetchPostPut && + ai == other.ai && + throttleStatic == other.throttleStatic && + throttleDynamic == other.throttleDynamic && + exit == other.exit && + branch == other.branch + } + + override fun hashCode(): Int = + Objects.hash( + apiInvokeTrigger, + segmentTrigger, + send, + delayDuration, + delayUntil, + fetchGetDelete, + fetchPostPut, + ai, + throttleStatic, + throttleDynamic, + exit, + branch, + ) + + override fun toString(): String = + when { + apiInvokeTrigger != null -> "JourneyNode{apiInvokeTrigger=$apiInvokeTrigger}" + segmentTrigger != null -> "JourneyNode{segmentTrigger=$segmentTrigger}" + send != null -> "JourneyNode{send=$send}" + delayDuration != null -> "JourneyNode{delayDuration=$delayDuration}" + delayUntil != null -> "JourneyNode{delayUntil=$delayUntil}" + fetchGetDelete != null -> "JourneyNode{fetchGetDelete=$fetchGetDelete}" + fetchPostPut != null -> "JourneyNode{fetchPostPut=$fetchPostPut}" + ai != null -> "JourneyNode{ai=$ai}" + throttleStatic != null -> "JourneyNode{throttleStatic=$throttleStatic}" + throttleDynamic != null -> "JourneyNode{throttleDynamic=$throttleDynamic}" + exit != null -> "JourneyNode{exit=$exit}" + branch != null -> "JourneyNode{branch=$branch}" + _json != null -> "JourneyNode{_unknown=$_json}" + else -> throw IllegalStateException("Invalid JourneyNode") + } + + companion object { + + /** + * Trigger fired when the journey is invoked via the API. The optional `schema` field is a + * JSON Schema that validates the invocation payload. + */ + @JvmStatic + fun ofApiInvokeTrigger(apiInvokeTrigger: JourneyApiInvokeTriggerNode) = + JourneyNode(apiInvokeTrigger = apiInvokeTrigger) + + /** Trigger fired by a segment event (`identify`, `group`, or `track`). */ + @JvmStatic + fun ofSegmentTrigger(segmentTrigger: JourneySegmentTriggerNode) = + JourneyNode(segmentTrigger = segmentTrigger) + + /** + * Send a notification template to the recipient. Optionally override the recipient address, + * delay the send, or attach `data`. + */ + @JvmStatic fun ofSend(send: JourneySendNode) = JourneyNode(send = send) + + /** Pause the journey run for a fixed `duration`. */ + @JvmStatic + fun ofDelayDuration(delayDuration: JourneyDelayDurationNode) = + JourneyNode(delayDuration = delayDuration) + + /** Pause the journey run `until` a specific time. */ + @JvmStatic + fun ofDelayUntil(delayUntil: JourneyDelayUntilNode) = JourneyNode(delayUntil = delayUntil) + + /** + * Issue an HTTP GET or DELETE request and merge the response into the journey state per + * `merge_strategy`. + */ + @JvmStatic + fun ofFetchGetDelete(fetchGetDelete: JourneyFetchGetDeleteNode) = + JourneyNode(fetchGetDelete = fetchGetDelete) + + /** + * Issue an HTTP POST or PUT request with a `body` and merge the response into the journey + * state per `merge_strategy`. + */ + @JvmStatic + fun ofFetchPostPut(fetchPostPut: JourneyFetchPostPutNode) = + JourneyNode(fetchPostPut = fetchPostPut) + + /** + * Invoke an AI step with `user_prompt` and optional `web_search`. Returns a structured + * response conforming to `output_schema`. + */ + @JvmStatic fun ofAi(ai: JourneyAiNode) = JourneyNode(ai = ai) + + /** + * Throttle the journey by a static `scope` (`user` or `global`), allowing at most + * `max_allowed` invocations per `period`. + */ + @JvmStatic + fun ofThrottleStatic(throttleStatic: JourneyThrottleStaticNode) = + JourneyNode(throttleStatic = throttleStatic) + + /** + * Throttle the journey by a dynamic `throttle_key`, allowing at most `max_allowed` + * invocations per `period`. + */ + @JvmStatic + fun ofThrottleDynamic(throttleDynamic: JourneyThrottleDynamicNode) = + JourneyNode(throttleDynamic = throttleDynamic) + + /** Terminate the journey run. */ + @JvmStatic fun ofExit(exit: JourneyExitNode) = JourneyNode(exit = exit) + + /** + * Branch node. Routes to the first entry in `paths[]` whose `conditions` match, else falls + * through to `default.nodes`. + */ + @JvmStatic fun ofBranch(branch: JourneyBranchNode) = JourneyNode(branch = branch) + } + + /** + * An interface that defines how to map each variant of [JourneyNode] to a value of type [T]. + */ + interface Visitor { + + /** + * Trigger fired when the journey is invoked via the API. The optional `schema` field is a + * JSON Schema that validates the invocation payload. + */ + fun visitApiInvokeTrigger(apiInvokeTrigger: JourneyApiInvokeTriggerNode): T + + /** Trigger fired by a segment event (`identify`, `group`, or `track`). */ + fun visitSegmentTrigger(segmentTrigger: JourneySegmentTriggerNode): T + + /** + * Send a notification template to the recipient. Optionally override the recipient address, + * delay the send, or attach `data`. + */ + fun visitSend(send: JourneySendNode): T + + /** Pause the journey run for a fixed `duration`. */ + fun visitDelayDuration(delayDuration: JourneyDelayDurationNode): T + + /** Pause the journey run `until` a specific time. */ + fun visitDelayUntil(delayUntil: JourneyDelayUntilNode): T + + /** + * Issue an HTTP GET or DELETE request and merge the response into the journey state per + * `merge_strategy`. + */ + fun visitFetchGetDelete(fetchGetDelete: JourneyFetchGetDeleteNode): T + + /** + * Issue an HTTP POST or PUT request with a `body` and merge the response into the journey + * state per `merge_strategy`. + */ + fun visitFetchPostPut(fetchPostPut: JourneyFetchPostPutNode): T + + /** + * Invoke an AI step with `user_prompt` and optional `web_search`. Returns a structured + * response conforming to `output_schema`. + */ + fun visitAi(ai: JourneyAiNode): T + + /** + * Throttle the journey by a static `scope` (`user` or `global`), allowing at most + * `max_allowed` invocations per `period`. + */ + fun visitThrottleStatic(throttleStatic: JourneyThrottleStaticNode): T + + /** + * Throttle the journey by a dynamic `throttle_key`, allowing at most `max_allowed` + * invocations per `period`. + */ + fun visitThrottleDynamic(throttleDynamic: JourneyThrottleDynamicNode): T + + /** Terminate the journey run. */ + fun visitExit(exit: JourneyExitNode): T + + /** + * Branch node. Routes to the first entry in `paths[]` whose `conditions` match, else falls + * through to `default.nodes`. + */ + fun visitBranch(branch: JourneyBranchNode): T + + /** + * Maps an unknown variant of [JourneyNode] to a value of type [T]. + * + * An instance of [JourneyNode] 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 JourneyNode: $json") + } + } + + internal class Deserializer : BaseDeserializer(JourneyNode::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): JourneyNode { + val json = JsonValue.fromJsonNode(node) + + val bestMatches = + sequenceOf( + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(apiInvokeTrigger = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(segmentTrigger = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(send = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(delayDuration = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(delayUntil = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(fetchGetDelete = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(fetchPostPut = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(ai = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(throttleStatic = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(throttleDynamic = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(exit = it, _json = json) + }, + tryDeserialize(node, jacksonTypeRef())?.let { + JourneyNode(branch = 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 -> JourneyNode(_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(JourneyNode::class) { + + override fun serialize( + value: JourneyNode, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + when { + value.apiInvokeTrigger != null -> generator.writeObject(value.apiInvokeTrigger) + value.segmentTrigger != null -> generator.writeObject(value.segmentTrigger) + value.send != null -> generator.writeObject(value.send) + value.delayDuration != null -> generator.writeObject(value.delayDuration) + value.delayUntil != null -> generator.writeObject(value.delayUntil) + value.fetchGetDelete != null -> generator.writeObject(value.fetchGetDelete) + value.fetchPostPut != null -> generator.writeObject(value.fetchPostPut) + value.ai != null -> generator.writeObject(value.ai) + value.throttleStatic != null -> generator.writeObject(value.throttleStatic) + value.throttleDynamic != null -> generator.writeObject(value.throttleDynamic) + value.exit != null -> generator.writeObject(value.exit) + value.branch != null -> generator.writeObject(value.branch) + value._json != null -> generator.writeObject(value._json) + else -> throw IllegalStateException("Invalid JourneyNode") + } + } + } + + /** + * Branch node. Routes to the first entry in `paths[]` whose `conditions` match, else falls + * through to `default.nodes`. + */ + class JourneyBranchNode + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val default_: JsonField, + private val paths: JsonField>, + private val type: JsonField, + private val id: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("default") + @ExcludeMissing + default_: JsonField = JsonMissing.of(), + @JsonProperty("paths") @ExcludeMissing paths: JsonField> = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + ) : this(default_, paths, type, id, 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). + */ + fun default_(): Default = default_.getRequired("default") + + /** + * @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 paths(): List = paths.getRequired("paths") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Returns the raw JSON value of [default_]. + * + * Unlike [default_], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("default") @ExcludeMissing fun _default_(): JsonField = default_ + + /** + * Returns the raw JSON value of [paths]. + * + * Unlike [paths], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("paths") @ExcludeMissing fun _paths(): JsonField> = paths + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyBranchNode]. + * + * The following fields are required: + * ```java + * .default_() + * .paths() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyBranchNode]. */ + class Builder internal constructor() { + + private var default_: JsonField? = null + private var paths: JsonField>? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyBranchNode: JourneyBranchNode) = apply { + default_ = journeyBranchNode.default_ + paths = journeyBranchNode.paths.map { it.toMutableList() } + type = journeyBranchNode.type + id = journeyBranchNode.id + additionalProperties = journeyBranchNode.additionalProperties.toMutableMap() + } + + fun default_(default_: Default) = default_(JsonField.of(default_)) + + /** + * Sets [Builder.default_] to an arbitrary JSON value. + * + * You should usually call [Builder.default_] with a well-typed [Default] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun default_(default_: JsonField) = apply { this.default_ = default_ } + + fun paths(paths: List) = paths(JsonField.of(paths)) + + /** + * Sets [Builder.paths] to an arbitrary JSON value. + * + * You should usually call [Builder.paths] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun paths(paths: JsonField>) = apply { + this.paths = paths.map { it.toMutableList() } + } + + /** + * Adds a single [Path] to [paths]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addPath(path: Path) = apply { + paths = + (paths ?: JsonField.of(mutableListOf())).also { + checkKnown("paths", it).add(path) + } + } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + 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 [JourneyBranchNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .default_() + * .paths() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyBranchNode = + JourneyBranchNode( + checkRequired("default_", default_), + checkRequired("paths", paths).map { it.toImmutable() }, + checkRequired("type", type), + id, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyBranchNode = apply { + if (validated) { + return@apply + } + + default_().validate() + paths().forEach { it.validate() } + type().validate() + id() + 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 = + (default_.asKnown().getOrNull()?.validity() ?: 0) + + (paths.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + class Default + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val nodes: JsonField>, + private val label: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("nodes") + @ExcludeMissing + nodes: JsonField> = JsonMissing.of(), + @JsonProperty("label") @ExcludeMissing label: JsonField = JsonMissing.of(), + ) : this(nodes, label, 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). + */ + fun nodes(): List = nodes.getRequired("nodes") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun label(): Optional = label.getOptional("label") + + /** + * Returns the raw JSON value of [nodes]. + * + * Unlike [nodes], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nodes") + @ExcludeMissing + fun _nodes(): JsonField> = nodes + + /** + * Returns the raw JSON value of [label]. + * + * Unlike [label], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("label") @ExcludeMissing fun _label(): JsonField = label + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Default]. + * + * The following fields are required: + * ```java + * .nodes() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Default]. */ + class Builder internal constructor() { + + private var nodes: JsonField>? = null + private var label: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(default_: Default) = apply { + nodes = default_.nodes.map { it.toMutableList() } + label = default_.label + additionalProperties = default_.additionalProperties.toMutableMap() + } + + fun nodes(nodes: List) = nodes(JsonField.of(nodes)) + + /** + * Sets [Builder.nodes] to an arbitrary JSON value. + * + * You should usually call [Builder.nodes] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun nodes(nodes: JsonField>) = apply { + this.nodes = nodes.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyNode] to [nodes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addNode(node: JourneyNode) = apply { + nodes = + (nodes ?: JsonField.of(mutableListOf())).also { + checkKnown("nodes", it).add(node) + } + } + + /** + * Alias for calling [addNode] with + * `JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)`. + */ + fun addNode(apiInvokeTrigger: JourneyApiInvokeTriggerNode) = + addNode(JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofSegmentTrigger(segmentTrigger)`. + */ + fun addNode(segmentTrigger: JourneySegmentTriggerNode) = + addNode(JourneyNode.ofSegmentTrigger(segmentTrigger)) + + /** Alias for calling [addNode] with `JourneyNode.ofSend(send)`. */ + fun addNode(send: JourneySendNode) = addNode(JourneyNode.ofSend(send)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofDelayDuration(delayDuration)`. + */ + fun addNode(delayDuration: JourneyDelayDurationNode) = + addNode(JourneyNode.ofDelayDuration(delayDuration)) + + /** Alias for calling [addNode] with `JourneyNode.ofDelayUntil(delayUntil)`. */ + fun addNode(delayUntil: JourneyDelayUntilNode) = + addNode(JourneyNode.ofDelayUntil(delayUntil)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofFetchGetDelete(fetchGetDelete)`. + */ + fun addNode(fetchGetDelete: JourneyFetchGetDeleteNode) = + addNode(JourneyNode.ofFetchGetDelete(fetchGetDelete)) + + /** Alias for calling [addNode] with `JourneyNode.ofFetchPostPut(fetchPostPut)`. */ + fun addNode(fetchPostPut: JourneyFetchPostPutNode) = + addNode(JourneyNode.ofFetchPostPut(fetchPostPut)) + + /** Alias for calling [addNode] with `JourneyNode.ofAi(ai)`. */ + fun addNode(ai: JourneyAiNode) = addNode(JourneyNode.ofAi(ai)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofThrottleStatic(throttleStatic)`. + */ + fun addNode(throttleStatic: JourneyThrottleStaticNode) = + addNode(JourneyNode.ofThrottleStatic(throttleStatic)) + + /** + * Alias for calling [addNode] with + * `JourneyNode.ofThrottleDynamic(throttleDynamic)`. + */ + fun addNode(throttleDynamic: JourneyThrottleDynamicNode) = + addNode(JourneyNode.ofThrottleDynamic(throttleDynamic)) + + /** Alias for calling [addNode] with `JourneyNode.ofExit(exit)`. */ + fun addNode(exit: JourneyExitNode) = addNode(JourneyNode.ofExit(exit)) + + /** Alias for calling [addNode] with `JourneyNode.ofBranch(branch)`. */ + fun addNode(branch: JourneyBranchNode) = addNode(JourneyNode.ofBranch(branch)) + + fun label(label: String) = label(JsonField.of(label)) + + /** + * Sets [Builder.label] to an arbitrary JSON value. + * + * You should usually call [Builder.label] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun label(label: JsonField) = apply { this.label = label } + + 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 [Default]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .nodes() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Default = + Default( + checkRequired("nodes", nodes).map { it.toImmutable() }, + label, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Default = apply { + if (validated) { + return@apply + } + + nodes().forEach { it.validate() } + label() + 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 = + (nodes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (label.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Default && + nodes == other.nodes && + label == other.label && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(nodes, label, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Default{nodes=$nodes, label=$label, additionalProperties=$additionalProperties}" + } + + class Path + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val conditions: JsonField, + private val nodes: JsonField>, + private val label: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + @JsonProperty("nodes") + @ExcludeMissing + nodes: JsonField> = JsonMissing.of(), + @JsonProperty("label") @ExcludeMissing label: JsonField = JsonMissing.of(), + ) : this(conditions, nodes, label, mutableMapOf()) + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, + * or an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + * + * @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 conditions(): JourneyConditionsField = conditions.getRequired("conditions") + + /** + * @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 nodes(): List = nodes.getRequired("nodes") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun label(): Optional = label.getOptional("label") + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + /** + * Returns the raw JSON value of [nodes]. + * + * Unlike [nodes], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nodes") + @ExcludeMissing + fun _nodes(): JsonField> = nodes + + /** + * Returns the raw JSON value of [label]. + * + * Unlike [label], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("label") @ExcludeMissing fun _label(): JsonField = label + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Path]. + * + * The following fields are required: + * ```java + * .conditions() + * .nodes() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Path]. */ + class Builder internal constructor() { + + private var conditions: JsonField? = null + private var nodes: JsonField>? = null + private var label: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(path: Path) = apply { + conditions = path.conditions + nodes = path.nodes.map { it.toMutableList() } + label = path.label + additionalProperties = path.additionalProperties.toMutableMap() + } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR + * group, or an AND/OR nested group. Omit the `conditions` property entirely to + * express "no conditions". + */ + fun conditions(conditions: JourneyConditionsField) = + conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed + * [JourneyConditionsField] value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + fun nodes(nodes: List) = nodes(JsonField.of(nodes)) + + /** + * Sets [Builder.nodes] to an arbitrary JSON value. + * + * You should usually call [Builder.nodes] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun nodes(nodes: JsonField>) = apply { + this.nodes = nodes.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyNode] to [nodes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addNode(node: JourneyNode) = apply { + nodes = + (nodes ?: JsonField.of(mutableListOf())).also { + checkKnown("nodes", it).add(node) + } + } + + /** + * Alias for calling [addNode] with + * `JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)`. + */ + fun addNode(apiInvokeTrigger: JourneyApiInvokeTriggerNode) = + addNode(JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofSegmentTrigger(segmentTrigger)`. + */ + fun addNode(segmentTrigger: JourneySegmentTriggerNode) = + addNode(JourneyNode.ofSegmentTrigger(segmentTrigger)) + + /** Alias for calling [addNode] with `JourneyNode.ofSend(send)`. */ + fun addNode(send: JourneySendNode) = addNode(JourneyNode.ofSend(send)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofDelayDuration(delayDuration)`. + */ + fun addNode(delayDuration: JourneyDelayDurationNode) = + addNode(JourneyNode.ofDelayDuration(delayDuration)) + + /** Alias for calling [addNode] with `JourneyNode.ofDelayUntil(delayUntil)`. */ + fun addNode(delayUntil: JourneyDelayUntilNode) = + addNode(JourneyNode.ofDelayUntil(delayUntil)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofFetchGetDelete(fetchGetDelete)`. + */ + fun addNode(fetchGetDelete: JourneyFetchGetDeleteNode) = + addNode(JourneyNode.ofFetchGetDelete(fetchGetDelete)) + + /** Alias for calling [addNode] with `JourneyNode.ofFetchPostPut(fetchPostPut)`. */ + fun addNode(fetchPostPut: JourneyFetchPostPutNode) = + addNode(JourneyNode.ofFetchPostPut(fetchPostPut)) + + /** Alias for calling [addNode] with `JourneyNode.ofAi(ai)`. */ + fun addNode(ai: JourneyAiNode) = addNode(JourneyNode.ofAi(ai)) + + /** + * Alias for calling [addNode] with `JourneyNode.ofThrottleStatic(throttleStatic)`. + */ + fun addNode(throttleStatic: JourneyThrottleStaticNode) = + addNode(JourneyNode.ofThrottleStatic(throttleStatic)) + + /** + * Alias for calling [addNode] with + * `JourneyNode.ofThrottleDynamic(throttleDynamic)`. + */ + fun addNode(throttleDynamic: JourneyThrottleDynamicNode) = + addNode(JourneyNode.ofThrottleDynamic(throttleDynamic)) + + /** Alias for calling [addNode] with `JourneyNode.ofExit(exit)`. */ + fun addNode(exit: JourneyExitNode) = addNode(JourneyNode.ofExit(exit)) + + /** Alias for calling [addNode] with `JourneyNode.ofBranch(branch)`. */ + fun addNode(branch: JourneyBranchNode) = addNode(JourneyNode.ofBranch(branch)) + + fun label(label: String) = label(JsonField.of(label)) + + /** + * Sets [Builder.label] to an arbitrary JSON value. + * + * You should usually call [Builder.label] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun label(label: JsonField) = apply { this.label = label } + + 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 [Path]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .conditions() + * .nodes() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Path = + Path( + checkRequired("conditions", conditions), + checkRequired("nodes", nodes).map { it.toImmutable() }, + label, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Path = apply { + if (validated) { + return@apply + } + + conditions().validate() + nodes().forEach { it.validate() } + label() + 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 = + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + (nodes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (label.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Path && + conditions == other.conditions && + nodes == other.nodes && + label == other.label && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(conditions, nodes, label, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Path{conditions=$conditions, nodes=$nodes, label=$label, additionalProperties=$additionalProperties}" + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val BRANCH = of("branch") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + BRANCH + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + BRANCH, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + BRANCH -> Value.BRANCH + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + BRANCH -> Known.BRANCH + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CourierInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyBranchNode && + default_ == other.default_ && + paths == other.paths && + type == other.type && + id == other.id && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(default_, paths, type, id, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyBranchNode{default_=$default_, paths=$paths, type=$type, id=$id, additionalProperties=$additionalProperties}" + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishParams.kt new file mode 100644 index 00000000..8c07fd58 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishParams.kt @@ -0,0 +1,231 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.core.immutableEmptyMap +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Publish the current draft as a new version. Body is optional; pass `{ "version": "vN" }` to roll + * back to a prior version instead. Returns 404 if the journey has no draft to publish. + */ +class JourneyPublishParams +private constructor( + private val templateId: String?, + private val journeyPublishRequest: JourneyPublishRequest?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** + * Request body for publishing a journey. Pass `version` to roll back to a prior version; omit + * to publish the current draft. + */ + fun journeyPublishRequest(): Optional = + Optional.ofNullable(journeyPublishRequest) + + fun _additionalBodyProperties(): Map = + journeyPublishRequest?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): JourneyPublishParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [JourneyPublishParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyPublishParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var journeyPublishRequest: JourneyPublishRequest? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(journeyPublishParams: JourneyPublishParams) = apply { + templateId = journeyPublishParams.templateId + journeyPublishRequest = journeyPublishParams.journeyPublishRequest + additionalHeaders = journeyPublishParams.additionalHeaders.toBuilder() + additionalQueryParams = journeyPublishParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + /** + * Request body for publishing a journey. Pass `version` to roll back to a prior version; + * omit to publish the current draft. + */ + fun journeyPublishRequest(journeyPublishRequest: JourneyPublishRequest?) = apply { + this.journeyPublishRequest = journeyPublishRequest + } + + /** + * Alias for calling [Builder.journeyPublishRequest] with + * `journeyPublishRequest.orElse(null)`. + */ + fun journeyPublishRequest(journeyPublishRequest: Optional) = + journeyPublishRequest(journeyPublishRequest.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [JourneyPublishParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyPublishParams = + JourneyPublishParams( + templateId, + journeyPublishRequest, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Optional = Optional.ofNullable(journeyPublishRequest) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyPublishParams && + templateId == other.templateId && + journeyPublishRequest == other.journeyPublishRequest && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(templateId, journeyPublishRequest, additionalHeaders, additionalQueryParams) + + override fun toString() = + "JourneyPublishParams{templateId=$templateId, journeyPublishRequest=$journeyPublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishRequest.kt new file mode 100644 index 00000000..bfcbcaa1 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyPublishRequest.kt @@ -0,0 +1,165 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional + +/** + * Request body for publishing a journey. Pass `version` to roll back to a prior version; omit to + * publish the current draft. + */ +class JourneyPublishRequest +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val version: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("version") @ExcludeMissing version: JsonField = JsonMissing.of() + ) : this(version, mutableMapOf()) + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun version(): Optional = version.getOptional("version") + + /** + * Returns the raw JSON value of [version]. + * + * Unlike [version], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [JourneyPublishRequest]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyPublishRequest]. */ + class Builder internal constructor() { + + private var version: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyPublishRequest: JourneyPublishRequest) = apply { + version = journeyPublishRequest.version + additionalProperties = journeyPublishRequest.additionalProperties.toMutableMap() + } + + fun version(version: String) = version(JsonField.of(version)) + + /** + * Sets [Builder.version] to an arbitrary JSON value. + * + * You should usually call [Builder.version] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun version(version: JsonField) = apply { this.version = version } + + 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 [JourneyPublishRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyPublishRequest = + JourneyPublishRequest(version, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyPublishRequest = apply { + if (validated) { + return@apply + } + + version() + 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 = (if (version.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyPublishRequest && + version == other.version && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(version, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyPublishRequest{version=$version, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyReplaceParams.kt new file mode 100644 index 00000000..40365c98 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyReplaceParams.kt @@ -0,0 +1,231 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Replace the journey draft. Updates the working draft only; call `POST + * /journeys/{templateId}/publish` to make it live, or pass `state: "PUBLISHED"` in this request to + * publish immediately. Send-node `template` ids must already exist and be scoped to this journey, + * and node ids must not be claimed by another journey. + */ +class JourneyReplaceParams +private constructor( + private val templateId: String?, + private val createJourneyRequest: CreateJourneyRequest, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** Request body for creating a journey. */ + fun createJourneyRequest(): CreateJourneyRequest = createJourneyRequest + + fun _additionalBodyProperties(): Map = + createJourneyRequest._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyReplaceParams]. + * + * The following fields are required: + * ```java + * .createJourneyRequest() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyReplaceParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var createJourneyRequest: CreateJourneyRequest? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(journeyReplaceParams: JourneyReplaceParams) = apply { + templateId = journeyReplaceParams.templateId + createJourneyRequest = journeyReplaceParams.createJourneyRequest + additionalHeaders = journeyReplaceParams.additionalHeaders.toBuilder() + additionalQueryParams = journeyReplaceParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + /** Request body for creating a journey. */ + fun createJourneyRequest(createJourneyRequest: CreateJourneyRequest) = apply { + this.createJourneyRequest = createJourneyRequest + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [JourneyReplaceParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .createJourneyRequest() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyReplaceParams = + JourneyReplaceParams( + templateId, + checkRequired("createJourneyRequest", createJourneyRequest), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): CreateJourneyRequest = createJourneyRequest + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyReplaceParams && + templateId == other.templateId && + createJourneyRequest == other.createJourneyRequest && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(templateId, createJourneyRequest, additionalHeaders, additionalQueryParams) + + override fun toString() = + "JourneyReplaceParams{templateId=$templateId, createJourneyRequest=$createJourneyRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyResponse.kt new file mode 100644 index 00000000..4ce60470 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyResponse.kt @@ -0,0 +1,607 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** A journey, with its current draft or published nodes and metadata. */ +class JourneyResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val created: JsonField, + private val creator: JsonField, + private val enabled: JsonField, + private val name: JsonField, + private val nodes: JsonField>, + private val published: JsonField, + private val state: JsonField, + private val updated: JsonField, + private val updater: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("created") @ExcludeMissing created: JsonField = JsonMissing.of(), + @JsonProperty("creator") @ExcludeMissing creator: JsonField = JsonMissing.of(), + @JsonProperty("enabled") @ExcludeMissing enabled: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("nodes") + @ExcludeMissing + nodes: JsonField> = JsonMissing.of(), + @JsonProperty("published") @ExcludeMissing published: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + @JsonProperty("updated") @ExcludeMissing updated: JsonField = JsonMissing.of(), + @JsonProperty("updater") @ExcludeMissing updater: JsonField = JsonMissing.of(), + ) : this( + id, + created, + creator, + enabled, + name, + nodes, + published, + state, + updated, + updater, + 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). + */ + fun id(): String = id.getRequired("id") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun created(): Optional = created.getOptional("created") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun creator(): Optional = creator.getOptional("creator") + + /** + * @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 enabled(): Boolean = enabled.getRequired("enabled") + + /** + * @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 name(): String = name.getRequired("name") + + /** + * @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 nodes(): List = nodes.getRequired("nodes") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun published(): Optional = published.getOptional("published") + + /** + * Lifecycle state of a journey. + * + * @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 state(): JourneyState = state.getRequired("state") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun updated(): Optional = updated.getOptional("updated") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun updater(): Optional = updater.getOptional("updater") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * Returns the raw JSON value of [creator]. + * + * Unlike [creator], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("creator") @ExcludeMissing fun _creator(): JsonField = creator + + /** + * Returns the raw JSON value of [enabled]. + * + * Unlike [enabled], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("enabled") @ExcludeMissing fun _enabled(): JsonField = enabled + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [nodes]. + * + * Unlike [nodes], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("nodes") @ExcludeMissing fun _nodes(): JsonField> = nodes + + /** + * Returns the raw JSON value of [published]. + * + * Unlike [published], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("published") @ExcludeMissing fun _published(): JsonField = published + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + /** + * Returns the raw JSON value of [updated]. + * + * Unlike [updated], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updated") @ExcludeMissing fun _updated(): JsonField = updated + + /** + * Returns the raw JSON value of [updater]. + * + * Unlike [updater], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updater") @ExcludeMissing fun _updater(): JsonField = updater + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyResponse]. + * + * The following fields are required: + * ```java + * .id() + * .created() + * .creator() + * .enabled() + * .name() + * .nodes() + * .published() + * .state() + * .updated() + * .updater() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyResponse]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var created: JsonField? = null + private var creator: JsonField? = null + private var enabled: JsonField? = null + private var name: JsonField? = null + private var nodes: JsonField>? = null + private var published: JsonField? = null + private var state: JsonField? = null + private var updated: JsonField? = null + private var updater: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyResponse: JourneyResponse) = apply { + id = journeyResponse.id + created = journeyResponse.created + creator = journeyResponse.creator + enabled = journeyResponse.enabled + name = journeyResponse.name + nodes = journeyResponse.nodes.map { it.toMutableList() } + published = journeyResponse.published + state = journeyResponse.state + updated = journeyResponse.updated + updater = journeyResponse.updater + additionalProperties = journeyResponse.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun created(created: Long?) = created(JsonField.ofNullable(created)) + + /** + * Alias for [Builder.created]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun created(created: Long) = created(created as Long?) + + /** Alias for calling [Builder.created] with `created.orElse(null)`. */ + fun created(created: Optional) = created(created.getOrNull()) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + fun creator(creator: String?) = creator(JsonField.ofNullable(creator)) + + /** Alias for calling [Builder.creator] with `creator.orElse(null)`. */ + fun creator(creator: Optional) = creator(creator.getOrNull()) + + /** + * Sets [Builder.creator] to an arbitrary JSON value. + * + * You should usually call [Builder.creator] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun creator(creator: JsonField) = apply { this.creator = creator } + + fun enabled(enabled: Boolean) = enabled(JsonField.of(enabled)) + + /** + * Sets [Builder.enabled] to an arbitrary JSON value. + * + * You should usually call [Builder.enabled] with a well-typed [Boolean] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun enabled(enabled: JsonField) = apply { this.enabled = enabled } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun nodes(nodes: List) = nodes(JsonField.of(nodes)) + + /** + * Sets [Builder.nodes] to an arbitrary JSON value. + * + * You should usually call [Builder.nodes] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun nodes(nodes: JsonField>) = apply { + this.nodes = nodes.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyNode] to [nodes]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addNode(node: JourneyNode) = apply { + nodes = + (nodes ?: JsonField.of(mutableListOf())).also { checkKnown("nodes", it).add(node) } + } + + /** Alias for calling [addNode] with `JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)`. */ + fun addNode(apiInvokeTrigger: JourneyApiInvokeTriggerNode) = + addNode(JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger)) + + /** Alias for calling [addNode] with `JourneyNode.ofSegmentTrigger(segmentTrigger)`. */ + fun addNode(segmentTrigger: JourneySegmentTriggerNode) = + addNode(JourneyNode.ofSegmentTrigger(segmentTrigger)) + + /** Alias for calling [addNode] with `JourneyNode.ofSend(send)`. */ + fun addNode(send: JourneySendNode) = addNode(JourneyNode.ofSend(send)) + + /** Alias for calling [addNode] with `JourneyNode.ofDelayDuration(delayDuration)`. */ + fun addNode(delayDuration: JourneyDelayDurationNode) = + addNode(JourneyNode.ofDelayDuration(delayDuration)) + + /** Alias for calling [addNode] with `JourneyNode.ofDelayUntil(delayUntil)`. */ + fun addNode(delayUntil: JourneyDelayUntilNode) = + addNode(JourneyNode.ofDelayUntil(delayUntil)) + + /** Alias for calling [addNode] with `JourneyNode.ofFetchGetDelete(fetchGetDelete)`. */ + fun addNode(fetchGetDelete: JourneyFetchGetDeleteNode) = + addNode(JourneyNode.ofFetchGetDelete(fetchGetDelete)) + + /** Alias for calling [addNode] with `JourneyNode.ofFetchPostPut(fetchPostPut)`. */ + fun addNode(fetchPostPut: JourneyFetchPostPutNode) = + addNode(JourneyNode.ofFetchPostPut(fetchPostPut)) + + /** Alias for calling [addNode] with `JourneyNode.ofAi(ai)`. */ + fun addNode(ai: JourneyAiNode) = addNode(JourneyNode.ofAi(ai)) + + /** Alias for calling [addNode] with `JourneyNode.ofThrottleStatic(throttleStatic)`. */ + fun addNode(throttleStatic: JourneyThrottleStaticNode) = + addNode(JourneyNode.ofThrottleStatic(throttleStatic)) + + /** Alias for calling [addNode] with `JourneyNode.ofThrottleDynamic(throttleDynamic)`. */ + fun addNode(throttleDynamic: JourneyThrottleDynamicNode) = + addNode(JourneyNode.ofThrottleDynamic(throttleDynamic)) + + /** Alias for calling [addNode] with `JourneyNode.ofExit(exit)`. */ + fun addNode(exit: JourneyExitNode) = addNode(JourneyNode.ofExit(exit)) + + /** Alias for calling [addNode] with `JourneyNode.ofBranch(branch)`. */ + fun addNode(branch: JourneyNode.JourneyBranchNode) = addNode(JourneyNode.ofBranch(branch)) + + fun published(published: Long?) = published(JsonField.ofNullable(published)) + + /** + * Alias for [Builder.published]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun published(published: Long) = published(published as Long?) + + /** Alias for calling [Builder.published] with `published.orElse(null)`. */ + fun published(published: Optional) = published(published.getOrNull()) + + /** + * Sets [Builder.published] to an arbitrary JSON value. + * + * You should usually call [Builder.published] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun published(published: JsonField) = apply { this.published = published } + + /** Lifecycle state of a journey. */ + fun state(state: JourneyState) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [JourneyState] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun state(state: JsonField) = apply { this.state = state } + + fun updated(updated: Long?) = updated(JsonField.ofNullable(updated)) + + /** + * Alias for [Builder.updated]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun updated(updated: Long) = updated(updated as Long?) + + /** Alias for calling [Builder.updated] with `updated.orElse(null)`. */ + fun updated(updated: Optional) = updated(updated.getOrNull()) + + /** + * Sets [Builder.updated] to an arbitrary JSON value. + * + * You should usually call [Builder.updated] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun updated(updated: JsonField) = apply { this.updated = updated } + + fun updater(updater: String?) = updater(JsonField.ofNullable(updater)) + + /** Alias for calling [Builder.updater] with `updater.orElse(null)`. */ + fun updater(updater: Optional) = updater(updater.getOrNull()) + + /** + * Sets [Builder.updater] to an arbitrary JSON value. + * + * You should usually call [Builder.updater] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun updater(updater: JsonField) = apply { this.updater = updater } + + 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 [JourneyResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .created() + * .creator() + * .enabled() + * .name() + * .nodes() + * .published() + * .state() + * .updated() + * .updater() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyResponse = + JourneyResponse( + checkRequired("id", id), + checkRequired("created", created), + checkRequired("creator", creator), + checkRequired("enabled", enabled), + checkRequired("name", name), + checkRequired("nodes", nodes).map { it.toImmutable() }, + checkRequired("published", published), + checkRequired("state", state), + checkRequired("updated", updated), + checkRequired("updater", updater), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyResponse = apply { + if (validated) { + return@apply + } + + id() + created() + creator() + enabled() + name() + nodes().forEach { it.validate() } + published() + state().validate() + updated() + updater() + 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 = + (if (id.asKnown().isPresent) 1 else 0) + + (if (created.asKnown().isPresent) 1 else 0) + + (if (creator.asKnown().isPresent) 1 else 0) + + (if (enabled.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (nodes.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (published.asKnown().isPresent) 1 else 0) + + (state.asKnown().getOrNull()?.validity() ?: 0) + + (if (updated.asKnown().isPresent) 1 else 0) + + (if (updater.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyResponse && + id == other.id && + created == other.created && + creator == other.creator && + enabled == other.enabled && + name == other.name && + nodes == other.nodes && + published == other.published && + state == other.state && + updated == other.updated && + updater == other.updater && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + id, + created, + creator, + enabled, + name, + nodes, + published, + state, + updated, + updater, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyResponse{id=$id, created=$created, creator=$creator, enabled=$enabled, name=$name, nodes=$nodes, published=$published, state=$state, updated=$updated, updater=$updater, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyRetrieveParams.kt new file mode 100644 index 00000000..d791596f --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyRetrieveParams.kt @@ -0,0 +1,217 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Fetch a journey by id. Pass `?version=draft` (default `published`) to retrieve the working draft, + * or `?version=vN` to retrieve a historical version. + */ +class JourneyRetrieveParams +private constructor( + private val templateId: String?, + private val version: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** Version selector: `draft`, `published` (default), or `vN`. */ + fun version(): Optional = Optional.ofNullable(version) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): JourneyRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [JourneyRetrieveParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyRetrieveParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var version: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(journeyRetrieveParams: JourneyRetrieveParams) = apply { + templateId = journeyRetrieveParams.templateId + version = journeyRetrieveParams.version + additionalHeaders = journeyRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = journeyRetrieveParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + /** Version selector: `draft`, `published` (default), or `vN`. */ + fun version(version: String?) = apply { this.version = version } + + /** Alias for calling [Builder.version] with `version.orElse(null)`. */ + fun version(version: Optional) = version(version.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [JourneyRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyRetrieveParams = + JourneyRetrieveParams( + templateId, + version, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + version?.let { put("version", it) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyRetrieveParams && + templateId == other.templateId && + version == other.version && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(templateId, version, additionalHeaders, additionalQueryParams) + + override fun toString() = + "JourneyRetrieveParams{templateId=$templateId, version=$version, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneySegmentTriggerNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneySegmentTriggerNode.kt new file mode 100644 index 00000000..5d9b2e81 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneySegmentTriggerNode.kt @@ -0,0 +1,797 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Trigger fired by a segment event (`identify`, `group`, or `track`). */ +class JourneySegmentTriggerNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val requestType: JsonField, + private val triggerType: JsonField, + private val type: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val eventId: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("request_type") + @ExcludeMissing + requestType: JsonField = JsonMissing.of(), + @JsonProperty("trigger_type") + @ExcludeMissing + triggerType: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + @JsonProperty("event_id") @ExcludeMissing eventId: JsonField = JsonMissing.of(), + ) : this(requestType, triggerType, type, id, conditions, eventId, 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). + */ + fun requestType(): RequestType = requestType.getRequired("request_type") + + /** + * @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 triggerType(): TriggerType = triggerType.getRequired("trigger_type") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun eventId(): Optional = eventId.getOptional("event_id") + + /** + * Returns the raw JSON value of [requestType]. + * + * Unlike [requestType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("request_type") + @ExcludeMissing + fun _requestType(): JsonField = requestType + + /** + * Returns the raw JSON value of [triggerType]. + * + * Unlike [triggerType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("trigger_type") + @ExcludeMissing + fun _triggerType(): JsonField = triggerType + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + /** + * Returns the raw JSON value of [eventId]. + * + * Unlike [eventId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("event_id") @ExcludeMissing fun _eventId(): JsonField = eventId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneySegmentTriggerNode]. + * + * The following fields are required: + * ```java + * .requestType() + * .triggerType() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneySegmentTriggerNode]. */ + class Builder internal constructor() { + + private var requestType: JsonField? = null + private var triggerType: JsonField? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var eventId: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeySegmentTriggerNode: JourneySegmentTriggerNode) = apply { + requestType = journeySegmentTriggerNode.requestType + triggerType = journeySegmentTriggerNode.triggerType + type = journeySegmentTriggerNode.type + id = journeySegmentTriggerNode.id + conditions = journeySegmentTriggerNode.conditions + eventId = journeySegmentTriggerNode.eventId + additionalProperties = journeySegmentTriggerNode.additionalProperties.toMutableMap() + } + + fun requestType(requestType: RequestType) = requestType(JsonField.of(requestType)) + + /** + * Sets [Builder.requestType] to an arbitrary JSON value. + * + * You should usually call [Builder.requestType] with a well-typed [RequestType] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun requestType(requestType: JsonField) = apply { + this.requestType = requestType + } + + fun triggerType(triggerType: TriggerType) = triggerType(JsonField.of(triggerType)) + + /** + * Sets [Builder.triggerType] to an arbitrary JSON value. + * + * You should usually call [Builder.triggerType] with a well-typed [TriggerType] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun triggerType(triggerType: JsonField) = apply { + this.triggerType = triggerType + } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + fun eventId(eventId: String) = eventId(JsonField.of(eventId)) + + /** + * Sets [Builder.eventId] to an arbitrary JSON value. + * + * You should usually call [Builder.eventId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun eventId(eventId: JsonField) = apply { this.eventId = eventId } + + 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 [JourneySegmentTriggerNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .requestType() + * .triggerType() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneySegmentTriggerNode = + JourneySegmentTriggerNode( + checkRequired("requestType", requestType), + checkRequired("triggerType", triggerType), + checkRequired("type", type), + id, + conditions, + eventId, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneySegmentTriggerNode = apply { + if (validated) { + return@apply + } + + requestType().validate() + triggerType().validate() + type().validate() + id() + conditions().ifPresent { it.validate() } + eventId() + 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 = + (requestType.asKnown().getOrNull()?.validity() ?: 0) + + (triggerType.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + (if (eventId.asKnown().isPresent) 1 else 0) + + class RequestType @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val IDENTIFY = of("identify") + + @JvmField val GROUP = of("group") + + @JvmField val TRACK = of("track") + + @JvmStatic fun of(value: String) = RequestType(JsonField.of(value)) + } + + /** An enum containing [RequestType]'s known values. */ + enum class Known { + IDENTIFY, + GROUP, + TRACK, + } + + /** + * An enum containing [RequestType]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [RequestType] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + IDENTIFY, + GROUP, + TRACK, + /** + * An enum member indicating that [RequestType] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + IDENTIFY -> Value.IDENTIFY + GROUP -> Value.GROUP + TRACK -> Value.TRACK + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + IDENTIFY -> Known.IDENTIFY + GROUP -> Known.GROUP + TRACK -> Known.TRACK + else -> throw CourierInvalidDataException("Unknown RequestType: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): RequestType = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is RequestType && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class TriggerType @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val SEGMENT = of("segment") + + @JvmStatic fun of(value: String) = TriggerType(JsonField.of(value)) + } + + /** An enum containing [TriggerType]'s known values. */ + enum class Known { + SEGMENT + } + + /** + * An enum containing [TriggerType]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [TriggerType] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + SEGMENT, + /** + * An enum member indicating that [TriggerType] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + SEGMENT -> Value.SEGMENT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + SEGMENT -> Known.SEGMENT + else -> throw CourierInvalidDataException("Unknown TriggerType: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): TriggerType = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TriggerType && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val TRIGGER = of("trigger") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + TRIGGER + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + TRIGGER, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + TRIGGER -> Value.TRIGGER + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + TRIGGER -> Known.TRIGGER + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneySegmentTriggerNode && + requestType == other.requestType && + triggerType == other.triggerType && + type == other.type && + id == other.id && + conditions == other.conditions && + eventId == other.eventId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(requestType, triggerType, type, id, conditions, eventId, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneySegmentTriggerNode{requestType=$requestType, triggerType=$triggerType, type=$type, id=$id, conditions=$conditions, eventId=$eventId, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneySendNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneySendNode.kt new file mode 100644 index 00000000..ee3b108e --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneySendNode.kt @@ -0,0 +1,1290 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Send a notification template to the recipient. Optionally override the recipient address, delay + * the send, or attach `data`. + */ +class JourneySendNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val message: JsonField, + private val type: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("message") @ExcludeMissing message: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + ) : this(message, type, id, conditions, 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). + */ + fun message(): Message = message.getRequired("message") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * Returns the raw JSON value of [message]. + * + * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneySendNode]. + * + * The following fields are required: + * ```java + * .message() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneySendNode]. */ + class Builder internal constructor() { + + private var message: JsonField? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeySendNode: JourneySendNode) = apply { + message = journeySendNode.message + type = journeySendNode.type + id = journeySendNode.id + conditions = journeySendNode.conditions + additionalProperties = journeySendNode.additionalProperties.toMutableMap() + } + + fun message(message: Message) = message(JsonField.of(message)) + + /** + * Sets [Builder.message] to an arbitrary JSON value. + * + * You should usually call [Builder.message] with a well-typed [Message] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun message(message: JsonField) = apply { this.message = message } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + 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 [JourneySendNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .message() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneySendNode = + JourneySendNode( + checkRequired("message", message), + checkRequired("type", type), + id, + conditions, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneySendNode = apply { + if (validated) { + return@apply + } + + message().validate() + type().validate() + id() + conditions().ifPresent { it.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 = + (message.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + class Message + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val template: JsonField, + private val data: JsonField, + private val delay: JsonField, + private val to: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("template") + @ExcludeMissing + template: JsonField = JsonMissing.of(), + @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), + @JsonProperty("delay") @ExcludeMissing delay: JsonField = JsonMissing.of(), + @JsonProperty("to") @ExcludeMissing to: JsonField = JsonMissing.of(), + ) : this(template, data, delay, to, 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). + */ + fun template(): String = template.getRequired("template") + + /** + * @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 delay(): Optional = delay.getOptional("delay") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun to(): Optional = to.getOptional("to") + + /** + * Returns the raw JSON value of [template]. + * + * Unlike [template], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("template") @ExcludeMissing fun _template(): JsonField = template + + /** + * 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 [delay]. + * + * Unlike [delay], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("delay") @ExcludeMissing fun _delay(): JsonField = delay + + /** + * Returns the raw JSON value of [to]. + * + * Unlike [to], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("to") @ExcludeMissing fun _to(): JsonField = to + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Message]. + * + * The following fields are required: + * ```java + * .template() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Message]. */ + class Builder internal constructor() { + + private var template: JsonField? = null + private var data: JsonField = JsonMissing.of() + private var delay: JsonField = JsonMissing.of() + private var to: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(message: Message) = apply { + template = message.template + data = message.data + delay = message.delay + to = message.to + additionalProperties = message.additionalProperties.toMutableMap() + } + + fun template(template: String) = template(JsonField.of(template)) + + /** + * 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 } + + fun data(data: Data) = data(JsonField.of(data)) + + /** + * 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 delay(delay: Delay) = delay(JsonField.of(delay)) + + /** + * Sets [Builder.delay] to an arbitrary JSON value. + * + * You should usually call [Builder.delay] with a well-typed [Delay] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun delay(delay: JsonField) = apply { this.delay = delay } + + fun to(to: To) = to(JsonField.of(to)) + + /** + * Sets [Builder.to] to an arbitrary JSON value. + * + * You should usually call [Builder.to] with a well-typed [To] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun to(to: JsonField) = apply { this.to = to } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Message]. + * + * 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(): Message = + Message( + checkRequired("template", template), + data, + delay, + to, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Message = apply { + if (validated) { + return@apply + } + + template() + data().ifPresent { it.validate() } + delay().ifPresent { it.validate() } + to().ifPresent { it.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 = + (if (template.asKnown().isPresent) 1 else 0) + + (data.asKnown().getOrNull()?.validity() ?: 0) + + (delay.asKnown().getOrNull()?.validity() ?: 0) + + (to.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() + } + + /** 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 + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): 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 Delay + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val until: JsonField, + private val timezone: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("until") @ExcludeMissing until: JsonField = JsonMissing.of(), + @JsonProperty("timezone") + @ExcludeMissing + timezone: JsonField = JsonMissing.of(), + ) : this(until, timezone, 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). + */ + fun until(): String = until.getRequired("until") + + /** + * @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") + + /** + * Returns the raw JSON value of [until]. + * + * Unlike [until], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("until") @ExcludeMissing fun _until(): JsonField = until + + /** + * 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 + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Delay]. + * + * The following fields are required: + * ```java + * .until() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Delay]. */ + class Builder internal constructor() { + + private var until: JsonField? = null + private var timezone: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(delay: Delay) = apply { + until = delay.until + timezone = delay.timezone + additionalProperties = delay.additionalProperties.toMutableMap() + } + + fun until(until: String) = until(JsonField.of(until)) + + /** + * Sets [Builder.until] to an arbitrary JSON value. + * + * You should usually call [Builder.until] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun until(until: JsonField) = apply { this.until = until } + + fun timezone(timezone: String) = timezone(JsonField.of(timezone)) + + /** + * 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 } + + 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 [Delay]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .until() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Delay = + Delay( + checkRequired("until", until), + timezone, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Delay = apply { + if (validated) { + return@apply + } + + until() + timezone() + 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 = + (if (until.asKnown().isPresent) 1 else 0) + + (if (timezone.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Delay && + until == other.until && + timezone == other.timezone && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(until, timezone, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Delay{until=$until, timezone=$timezone, additionalProperties=$additionalProperties}" + } + + class To + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val emailOverride: JsonField, + private val phoneNumberOverride: JsonField, + private val userIdOverride: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("email_override") + @ExcludeMissing + emailOverride: JsonField = JsonMissing.of(), + @JsonProperty("phone_number_override") + @ExcludeMissing + phoneNumberOverride: JsonField = JsonMissing.of(), + @JsonProperty("user_id_override") + @ExcludeMissing + userIdOverride: JsonField = JsonMissing.of(), + ) : this(emailOverride, phoneNumberOverride, userIdOverride, mutableMapOf()) + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun emailOverride(): Optional = emailOverride.getOptional("email_override") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun phoneNumberOverride(): Optional = + phoneNumberOverride.getOptional("phone_number_override") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun userIdOverride(): Optional = userIdOverride.getOptional("user_id_override") + + /** + * Returns the raw JSON value of [emailOverride]. + * + * Unlike [emailOverride], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("email_override") + @ExcludeMissing + fun _emailOverride(): JsonField = emailOverride + + /** + * Returns the raw JSON value of [phoneNumberOverride]. + * + * Unlike [phoneNumberOverride], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("phone_number_override") + @ExcludeMissing + fun _phoneNumberOverride(): JsonField = phoneNumberOverride + + /** + * Returns the raw JSON value of [userIdOverride]. + * + * Unlike [userIdOverride], this method doesn't throw if the JSON field has an + * unexpected type. + */ + @JsonProperty("user_id_override") + @ExcludeMissing + fun _userIdOverride(): JsonField = userIdOverride + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [To]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [To]. */ + class Builder internal constructor() { + + private var emailOverride: JsonField = JsonMissing.of() + private var phoneNumberOverride: JsonField = JsonMissing.of() + private var userIdOverride: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(to: To) = apply { + emailOverride = to.emailOverride + phoneNumberOverride = to.phoneNumberOverride + userIdOverride = to.userIdOverride + additionalProperties = to.additionalProperties.toMutableMap() + } + + fun emailOverride(emailOverride: String) = + emailOverride(JsonField.of(emailOverride)) + + /** + * Sets [Builder.emailOverride] to an arbitrary JSON value. + * + * You should usually call [Builder.emailOverride] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun emailOverride(emailOverride: JsonField) = apply { + this.emailOverride = emailOverride + } + + fun phoneNumberOverride(phoneNumberOverride: String) = + phoneNumberOverride(JsonField.of(phoneNumberOverride)) + + /** + * Sets [Builder.phoneNumberOverride] to an arbitrary JSON value. + * + * You should usually call [Builder.phoneNumberOverride] with a well-typed [String] + * value instead. This method is primarily for setting the field to an undocumented + * or not yet supported value. + */ + fun phoneNumberOverride(phoneNumberOverride: JsonField) = apply { + this.phoneNumberOverride = phoneNumberOverride + } + + fun userIdOverride(userIdOverride: String) = + userIdOverride(JsonField.of(userIdOverride)) + + /** + * Sets [Builder.userIdOverride] to an arbitrary JSON value. + * + * You should usually call [Builder.userIdOverride] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun userIdOverride(userIdOverride: JsonField) = apply { + this.userIdOverride = userIdOverride + } + + 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 [To]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): To = + To( + emailOverride, + phoneNumberOverride, + userIdOverride, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): To = apply { + if (validated) { + return@apply + } + + emailOverride() + phoneNumberOverride() + userIdOverride() + 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 = + (if (emailOverride.asKnown().isPresent) 1 else 0) + + (if (phoneNumberOverride.asKnown().isPresent) 1 else 0) + + (if (userIdOverride.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is To && + emailOverride == other.emailOverride && + phoneNumberOverride == other.phoneNumberOverride && + userIdOverride == other.userIdOverride && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + emailOverride, + phoneNumberOverride, + userIdOverride, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "To{emailOverride=$emailOverride, phoneNumberOverride=$phoneNumberOverride, userIdOverride=$userIdOverride, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Message && + template == other.template && + data == other.data && + delay == other.delay && + to == other.to && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(template, data, delay, to, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Message{template=$template, data=$data, delay=$delay, to=$to, additionalProperties=$additionalProperties}" + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val SEND = of("send") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + SEND + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + SEND, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + SEND -> Value.SEND + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + SEND -> Known.SEND + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneySendNode && + message == other.message && + type == other.type && + id == other.id && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(message, type, id, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneySendNode{message=$message, type=$type, id=$id, conditions=$conditions, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyState.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyState.kt new file mode 100644 index 00000000..c1724aa0 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyState.kt @@ -0,0 +1,139 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.JsonField +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonCreator + +/** Lifecycle state of a journey. */ +class JourneyState @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't match + * any known member, and you want to know that value. For example, if the SDK is on an older + * version than the API, then the API may respond with new members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DRAFT = of("DRAFT") + + @JvmField val PUBLISHED = of("PUBLISHED") + + @JvmStatic fun of(value: String) = JourneyState(JsonField.of(value)) + } + + /** An enum containing [JourneyState]'s known values. */ + enum class Known { + DRAFT, + PUBLISHED, + } + + /** + * An enum containing [JourneyState]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [JourneyState] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the SDK + * is on an older version than the API, then the API may respond with new members that the SDK + * is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DRAFT, + PUBLISHED, + /** An enum member indicating that [JourneyState] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] if + * the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want to + * throw for the unknown case. + */ + fun value(): Value = + when (this) { + DRAFT -> Value.DRAFT + PUBLISHED -> Value.PUBLISHED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't want + * to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known member. + */ + fun known(): Known = + when (this) { + DRAFT -> Known.DRAFT + PUBLISHED -> Known.PUBLISHED + else -> throw CourierInvalidDataException("Unknown JourneyState: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging and + * generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the expected + * primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyState = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyState && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateCreateRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateCreateRequest.kt new file mode 100644 index 00000000..c92d4d75 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateCreateRequest.kt @@ -0,0 +1,1566 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.courier.models.ElementalActionNodeWithType +import com.courier.models.ElementalChannelNodeWithType +import com.courier.models.ElementalDividerNodeWithType +import com.courier.models.ElementalHtmlNodeWithType +import com.courier.models.ElementalImageNodeWithType +import com.courier.models.ElementalMetaNodeWithType +import com.courier.models.ElementalNode +import com.courier.models.ElementalQuoteNodeWithType +import com.courier.models.ElementalTextNodeWithType +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Request body for creating a notification template scoped to a journey. */ +class JourneyTemplateCreateRequest +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val channel: JsonField, + private val notification: JsonField, + private val providerKey: JsonField, + private val state: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("channel") @ExcludeMissing channel: JsonField = JsonMissing.of(), + @JsonProperty("notification") + @ExcludeMissing + notification: JsonField = JsonMissing.of(), + @JsonProperty("providerKey") + @ExcludeMissing + providerKey: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + ) : this(channel, notification, providerKey, state, 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). + */ + fun channel(): String = channel.getRequired("channel") + + /** + * @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 notification(): Notification = notification.getRequired("notification") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun providerKey(): Optional = providerKey.getOptional("providerKey") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun state(): Optional = state.getOptional("state") + + /** + * Returns the raw JSON value of [channel]. + * + * Unlike [channel], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("channel") @ExcludeMissing fun _channel(): JsonField = channel + + /** + * Returns the raw JSON value of [notification]. + * + * Unlike [notification], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("notification") + @ExcludeMissing + fun _notification(): JsonField = notification + + /** + * Returns the raw JSON value of [providerKey]. + * + * Unlike [providerKey], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("providerKey") @ExcludeMissing fun _providerKey(): JsonField = providerKey + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyTemplateCreateRequest]. + * + * The following fields are required: + * ```java + * .channel() + * .notification() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyTemplateCreateRequest]. */ + class Builder internal constructor() { + + private var channel: JsonField? = null + private var notification: JsonField? = null + private var providerKey: JsonField = JsonMissing.of() + private var state: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyTemplateCreateRequest: JourneyTemplateCreateRequest) = apply { + channel = journeyTemplateCreateRequest.channel + notification = journeyTemplateCreateRequest.notification + providerKey = journeyTemplateCreateRequest.providerKey + state = journeyTemplateCreateRequest.state + additionalProperties = journeyTemplateCreateRequest.additionalProperties.toMutableMap() + } + + fun channel(channel: String) = channel(JsonField.of(channel)) + + /** + * Sets [Builder.channel] to an arbitrary JSON value. + * + * You should usually call [Builder.channel] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun channel(channel: JsonField) = apply { this.channel = channel } + + fun notification(notification: Notification) = notification(JsonField.of(notification)) + + /** + * Sets [Builder.notification] to an arbitrary JSON value. + * + * You should usually call [Builder.notification] with a well-typed [Notification] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun notification(notification: JsonField) = apply { + this.notification = notification + } + + fun providerKey(providerKey: String) = providerKey(JsonField.of(providerKey)) + + /** + * Sets [Builder.providerKey] to an arbitrary JSON value. + * + * You should usually call [Builder.providerKey] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun providerKey(providerKey: JsonField) = apply { this.providerKey = providerKey } + + fun state(state: String) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun state(state: JsonField) = apply { this.state = state } + + 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 [JourneyTemplateCreateRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .channel() + * .notification() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyTemplateCreateRequest = + JourneyTemplateCreateRequest( + checkRequired("channel", channel), + checkRequired("notification", notification), + providerKey, + state, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyTemplateCreateRequest = apply { + if (validated) { + return@apply + } + + channel() + notification().validate() + providerKey() + state() + 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 = + (if (channel.asKnown().isPresent) 1 else 0) + + (notification.asKnown().getOrNull()?.validity() ?: 0) + + (if (providerKey.asKnown().isPresent) 1 else 0) + + (if (state.asKnown().isPresent) 1 else 0) + + class Notification + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val brand: JsonField, + private val content: JsonField, + private val name: JsonField, + private val subscription: JsonField, + private val tags: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("brand") @ExcludeMissing brand: JsonField = JsonMissing.of(), + @JsonProperty("content") @ExcludeMissing content: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("subscription") + @ExcludeMissing + subscription: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + ) : this(brand, content, name, subscription, tags, mutableMapOf()) + + /** + * @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 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun subscription(): Optional = subscription.getOptional("subscription") + + /** + * @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 tags(): List = tags.getRequired("tags") + + /** + * 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [subscription]. + * + * Unlike [subscription], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("subscription") + @ExcludeMissing + fun _subscription(): JsonField = subscription + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Notification]. + * + * The following fields are required: + * ```java + * .brand() + * .content() + * .name() + * .subscription() + * .tags() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Notification]. */ + class Builder internal constructor() { + + private var brand: JsonField? = null + private var content: JsonField? = null + private var name: JsonField? = null + private var subscription: JsonField? = null + private var tags: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(notification: Notification) = apply { + brand = notification.brand + content = notification.content + name = notification.name + subscription = notification.subscription + tags = notification.tags.map { it.toMutableList() } + additionalProperties = notification.additionalProperties.toMutableMap() + } + + fun brand(brand: Brand?) = 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 [Brand] 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 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 } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun subscription(subscription: Subscription?) = + subscription(JsonField.ofNullable(subscription)) + + /** Alias for calling [Builder.subscription] with `subscription.orElse(null)`. */ + fun subscription(subscription: Optional) = + subscription(subscription.getOrNull()) + + /** + * Sets [Builder.subscription] to an arbitrary JSON value. + * + * You should usually call [Builder.subscription] with a well-typed [Subscription] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun subscription(subscription: JsonField) = apply { + this.subscription = subscription + } + + fun tags(tags: List) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun tags(tags: JsonField>) = apply { + this.tags = tags.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: String) = apply { + tags = + (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + 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 [Notification]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .brand() + * .content() + * .name() + * .subscription() + * .tags() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Notification = + Notification( + checkRequired("brand", brand), + checkRequired("content", content), + checkRequired("name", name), + checkRequired("subscription", subscription), + checkRequired("tags", tags).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Notification = apply { + if (validated) { + return@apply + } + + brand().ifPresent { it.validate() } + content().validate() + name() + subscription().ifPresent { it.validate() } + tags() + 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 = + (brand.asKnown().getOrNull()?.validity() ?: 0) + + (content.asKnown().getOrNull()?.validity() ?: 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (subscription.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.size ?: 0) + + class Brand + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val id: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of() + ) : this(id, 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). + */ + fun id(): String = id.getRequired("id") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Brand]. + * + * The following fields are required: + * ```java + * .id() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Brand]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(brand: Brand) = apply { + id = brand.id + additionalProperties = brand.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + 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 [Brand]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Brand = + Brand(checkRequired("id", id), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Brand = apply { + if (validated) { + return@apply + } + + id() + 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 = (if (id.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Brand && + id == other.id && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Brand{id=$id, additionalProperties=$additionalProperties}" + } + + class Content + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val elements: JsonField>, + private val version: JsonField, + private val scope: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("elements") + @ExcludeMissing + elements: JsonField> = JsonMissing.of(), + @JsonProperty("version") + @ExcludeMissing + version: JsonField = JsonMissing.of(), + @JsonProperty("scope") @ExcludeMissing scope: JsonField = JsonMissing.of(), + ) : this(elements, version, scope, 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). + */ + fun elements(): List = elements.getRequired("elements") + + /** + * @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 version(): Version = version.getRequired("version") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun scope(): Optional = scope.getOptional("scope") + + /** + * Returns the raw JSON value of [elements]. + * + * Unlike [elements], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("elements") + @ExcludeMissing + fun _elements(): JsonField> = elements + + /** + * Returns the raw JSON value of [version]. + * + * Unlike [version], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version + + /** + * Returns the raw JSON value of [scope]. + * + * Unlike [scope], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("scope") @ExcludeMissing fun _scope(): JsonField = scope + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Content]. + * + * The following fields are required: + * ```java + * .elements() + * .version() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Content]. */ + class Builder internal constructor() { + + private var elements: JsonField>? = null + private var version: JsonField? = null + private var scope: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(content: Content) = apply { + elements = content.elements.map { it.toMutableList() } + version = content.version + scope = content.scope + additionalProperties = content.additionalProperties.toMutableMap() + } + + fun elements(elements: List) = elements(JsonField.of(elements)) + + /** + * Sets [Builder.elements] to an arbitrary JSON value. + * + * You should usually call [Builder.elements] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun elements(elements: JsonField>) = apply { + this.elements = elements.map { it.toMutableList() } + } + + /** + * Adds a single [ElementalNode] to [elements]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addElement(element: ElementalNode) = apply { + elements = + (elements ?: JsonField.of(mutableListOf())).also { + checkKnown("elements", it).add(element) + } + } + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofTextNodeWithType(textNodeWithType)`. + */ + fun addElement(textNodeWithType: ElementalTextNodeWithType) = + addElement(ElementalNode.ofTextNodeWithType(textNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofMetaNodeWithType(metaNodeWithType)`. + */ + fun addElement(metaNodeWithType: ElementalMetaNodeWithType) = + addElement(ElementalNode.ofMetaNodeWithType(metaNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofChannelNodeWithType(channelNodeWithType)`. + */ + fun addElement(channelNodeWithType: ElementalChannelNodeWithType) = + addElement(ElementalNode.ofChannelNodeWithType(channelNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofImageNodeWithType(imageNodeWithType)`. + */ + fun addElement(imageNodeWithType: ElementalImageNodeWithType) = + addElement(ElementalNode.ofImageNodeWithType(imageNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofActionNodeWithType(actionNodeWithType)`. + */ + fun addElement(actionNodeWithType: ElementalActionNodeWithType) = + addElement(ElementalNode.ofActionNodeWithType(actionNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofDividerNodeWithType(dividerNodeWithType)`. + */ + fun addElement(dividerNodeWithType: ElementalDividerNodeWithType) = + addElement(ElementalNode.ofDividerNodeWithType(dividerNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofQuoteNodeWithType(quoteNodeWithType)`. + */ + fun addElement(quoteNodeWithType: ElementalQuoteNodeWithType) = + addElement(ElementalNode.ofQuoteNodeWithType(quoteNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofHtmlNodeWithType(htmlNodeWithType)`. + */ + fun addElement(htmlNodeWithType: ElementalHtmlNodeWithType) = + addElement(ElementalNode.ofHtmlNodeWithType(htmlNodeWithType)) + + fun version(version: Version) = version(JsonField.of(version)) + + /** + * Sets [Builder.version] to an arbitrary JSON value. + * + * You should usually call [Builder.version] with a well-typed [Version] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun version(version: JsonField) = apply { this.version = version } + + fun scope(scope: Scope) = scope(JsonField.of(scope)) + + /** + * Sets [Builder.scope] to an arbitrary JSON value. + * + * You should usually call [Builder.scope] with a well-typed [Scope] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun scope(scope: JsonField) = apply { this.scope = scope } + + fun 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 [Content]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .elements() + * .version() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Content = + Content( + checkRequired("elements", elements).map { it.toImmutable() }, + checkRequired("version", version), + scope, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Content = apply { + if (validated) { + return@apply + } + + elements().forEach { it.validate() } + version().validate() + scope().ifPresent { it.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 = + (elements.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (version.asKnown().getOrNull()?.validity() ?: 0) + + (scope.asKnown().getOrNull()?.validity() ?: 0) + + class Version @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _2022_01_01 = of("2022-01-01") + + @JvmStatic fun of(value: String) = Version(JsonField.of(value)) + } + + /** An enum containing [Version]'s known values. */ + enum class Known { + _2022_01_01 + } + + /** + * An enum containing [Version]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Version] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _2022_01_01, + /** + * An enum member indicating that [Version] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _2022_01_01 -> Value._2022_01_01 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + _2022_01_01 -> Known._2022_01_01 + else -> throw CourierInvalidDataException("Unknown Version: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CourierInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): Version = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Version && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Scope @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DEFAULT = of("default") + + @JvmField val STRICT = of("strict") + + @JvmStatic fun of(value: String) = Scope(JsonField.of(value)) + } + + /** An enum containing [Scope]'s known values. */ + enum class Known { + DEFAULT, + STRICT, + } + + /** + * An enum containing [Scope]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Scope] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DEFAULT, + STRICT, + /** + * An enum member indicating that [Scope] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DEFAULT -> Value.DEFAULT + STRICT -> Value.STRICT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DEFAULT -> Known.DEFAULT + STRICT -> Known.STRICT + else -> throw CourierInvalidDataException("Unknown Scope: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CourierInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): Scope = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Scope && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Content && + elements == other.elements && + version == other.version && + scope == other.scope && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(elements, version, scope, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Content{elements=$elements, version=$version, scope=$scope, additionalProperties=$additionalProperties}" + } + + class Subscription + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val topicId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("topic_id") + @ExcludeMissing + topicId: JsonField = JsonMissing.of() + ) : this(topicId, 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). + */ + fun topicId(): String = topicId.getRequired("topic_id") + + /** + * Returns the raw JSON value of [topicId]. + * + * Unlike [topicId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("topic_id") @ExcludeMissing fun _topicId(): JsonField = topicId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Subscription]. + * + * The following fields are required: + * ```java + * .topicId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Subscription]. */ + class Builder internal constructor() { + + private var topicId: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(subscription: Subscription) = apply { + topicId = subscription.topicId + additionalProperties = subscription.additionalProperties.toMutableMap() + } + + fun topicId(topicId: String) = topicId(JsonField.of(topicId)) + + /** + * Sets [Builder.topicId] to an arbitrary JSON value. + * + * You should usually call [Builder.topicId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun topicId(topicId: JsonField) = apply { this.topicId = topicId } + + 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 [Subscription]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .topicId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Subscription = + Subscription( + checkRequired("topicId", topicId), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Subscription = apply { + if (validated) { + return@apply + } + + topicId() + 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 = (if (topicId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Subscription && + topicId == other.topicId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(topicId, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Subscription{topicId=$topicId, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Notification && + brand == other.brand && + content == other.content && + name == other.name && + subscription == other.subscription && + tags == other.tags && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(brand, content, name, subscription, tags, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Notification{brand=$brand, content=$content, name=$name, subscription=$subscription, tags=$tags, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyTemplateCreateRequest && + channel == other.channel && + notification == other.notification && + providerKey == other.providerKey && + state == other.state && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(channel, notification, providerKey, state, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyTemplateCreateRequest{channel=$channel, notification=$notification, providerKey=$providerKey, state=$state, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateGetResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateGetResponse.kt new file mode 100644 index 00000000..365d27fe --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateGetResponse.kt @@ -0,0 +1,1614 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.courier.models.ElementalActionNodeWithType +import com.courier.models.ElementalChannelNodeWithType +import com.courier.models.ElementalDividerNodeWithType +import com.courier.models.ElementalHtmlNodeWithType +import com.courier.models.ElementalImageNodeWithType +import com.courier.models.ElementalMetaNodeWithType +import com.courier.models.ElementalNode +import com.courier.models.ElementalQuoteNodeWithType +import com.courier.models.ElementalTextNodeWithType +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** A journey-scoped notification template. */ +class JourneyTemplateGetResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val brand: JsonField, + private val content: JsonField, + private val created: JsonField, + private val creator: JsonField, + private val name: JsonField, + private val state: JsonField, + private val subscription: JsonField, + private val tags: JsonField>, + private val updated: JsonField, + private val updater: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("brand") @ExcludeMissing brand: JsonField = JsonMissing.of(), + @JsonProperty("content") @ExcludeMissing content: JsonField = JsonMissing.of(), + @JsonProperty("created") @ExcludeMissing created: JsonField = JsonMissing.of(), + @JsonProperty("creator") @ExcludeMissing creator: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + @JsonProperty("subscription") + @ExcludeMissing + subscription: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + @JsonProperty("updated") @ExcludeMissing updated: JsonField = JsonMissing.of(), + @JsonProperty("updater") @ExcludeMissing updater: JsonField = JsonMissing.of(), + ) : this( + id, + brand, + content, + created, + creator, + name, + state, + subscription, + tags, + updated, + updater, + 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). + */ + fun id(): String = id.getRequired("id") + + /** + * @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 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun created(): Long = created.getRequired("created") + + /** + * @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 creator(): String = creator.getRequired("creator") + + /** + * @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 name(): String = name.getRequired("name") + + /** + * @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 state(): State = state.getRequired("state") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun subscription(): Optional = subscription.getOptional("subscription") + + /** + * @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 tags(): List = tags.getRequired("tags") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun updated(): Optional = updated.getOptional("updated") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun updater(): Optional = updater.getOptional("updater") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * 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 [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 [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * Returns the raw JSON value of [creator]. + * + * Unlike [creator], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("creator") @ExcludeMissing fun _creator(): JsonField = creator + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + /** + * Returns the raw JSON value of [subscription]. + * + * Unlike [subscription], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("subscription") + @ExcludeMissing + fun _subscription(): JsonField = subscription + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags + + /** + * Returns the raw JSON value of [updated]. + * + * Unlike [updated], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updated") @ExcludeMissing fun _updated(): JsonField = updated + + /** + * Returns the raw JSON value of [updater]. + * + * Unlike [updater], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updater") @ExcludeMissing fun _updater(): JsonField = updater + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyTemplateGetResponse]. + * + * The following fields are required: + * ```java + * .id() + * .brand() + * .content() + * .created() + * .creator() + * .name() + * .state() + * .subscription() + * .tags() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyTemplateGetResponse]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var brand: JsonField? = null + private var content: JsonField? = null + private var created: JsonField? = null + private var creator: JsonField? = null + private var name: JsonField? = null + private var state: JsonField? = null + private var subscription: JsonField? = null + private var tags: JsonField>? = null + private var updated: JsonField = JsonMissing.of() + private var updater: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyTemplateGetResponse: JourneyTemplateGetResponse) = apply { + id = journeyTemplateGetResponse.id + brand = journeyTemplateGetResponse.brand + content = journeyTemplateGetResponse.content + created = journeyTemplateGetResponse.created + creator = journeyTemplateGetResponse.creator + name = journeyTemplateGetResponse.name + state = journeyTemplateGetResponse.state + subscription = journeyTemplateGetResponse.subscription + tags = journeyTemplateGetResponse.tags.map { it.toMutableList() } + updated = journeyTemplateGetResponse.updated + updater = journeyTemplateGetResponse.updater + additionalProperties = journeyTemplateGetResponse.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun brand(brand: Brand?) = 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 [Brand] 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 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 } + + fun created(created: Long) = created(JsonField.of(created)) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + fun creator(creator: String) = creator(JsonField.of(creator)) + + /** + * Sets [Builder.creator] to an arbitrary JSON value. + * + * You should usually call [Builder.creator] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun creator(creator: JsonField) = apply { this.creator = creator } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun state(state: State) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [State] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun state(state: JsonField) = apply { this.state = state } + + fun subscription(subscription: Subscription?) = + subscription(JsonField.ofNullable(subscription)) + + /** Alias for calling [Builder.subscription] with `subscription.orElse(null)`. */ + fun subscription(subscription: Optional) = + subscription(subscription.getOrNull()) + + /** + * Sets [Builder.subscription] to an arbitrary JSON value. + * + * You should usually call [Builder.subscription] with a well-typed [Subscription] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun subscription(subscription: JsonField) = apply { + this.subscription = subscription + } + + fun tags(tags: List) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tags(tags: JsonField>) = apply { + this.tags = tags.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: String) = apply { + tags = (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + fun updated(updated: Long) = updated(JsonField.of(updated)) + + /** + * Sets [Builder.updated] to an arbitrary JSON value. + * + * You should usually call [Builder.updated] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun updated(updated: JsonField) = apply { this.updated = updated } + + fun updater(updater: String) = updater(JsonField.of(updater)) + + /** + * Sets [Builder.updater] to an arbitrary JSON value. + * + * You should usually call [Builder.updater] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun updater(updater: JsonField) = apply { this.updater = updater } + + 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 [JourneyTemplateGetResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .brand() + * .content() + * .created() + * .creator() + * .name() + * .state() + * .subscription() + * .tags() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyTemplateGetResponse = + JourneyTemplateGetResponse( + checkRequired("id", id), + checkRequired("brand", brand), + checkRequired("content", content), + checkRequired("created", created), + checkRequired("creator", creator), + checkRequired("name", name), + checkRequired("state", state), + checkRequired("subscription", subscription), + checkRequired("tags", tags).map { it.toImmutable() }, + updated, + updater, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyTemplateGetResponse = apply { + if (validated) { + return@apply + } + + id() + brand().ifPresent { it.validate() } + content().validate() + created() + creator() + name() + state().validate() + subscription().ifPresent { it.validate() } + tags() + updated() + updater() + 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 = + (if (id.asKnown().isPresent) 1 else 0) + + (brand.asKnown().getOrNull()?.validity() ?: 0) + + (content.asKnown().getOrNull()?.validity() ?: 0) + + (if (created.asKnown().isPresent) 1 else 0) + + (if (creator.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (state.asKnown().getOrNull()?.validity() ?: 0) + + (subscription.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.size ?: 0) + + (if (updated.asKnown().isPresent) 1 else 0) + + (if (updater.asKnown().isPresent) 1 else 0) + + class Brand + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val id: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of() + ) : this(id, 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). + */ + fun id(): String = id.getRequired("id") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Brand]. + * + * The following fields are required: + * ```java + * .id() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Brand]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(brand: Brand) = apply { + id = brand.id + additionalProperties = brand.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + 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 [Brand]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Brand = Brand(checkRequired("id", id), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Brand = apply { + if (validated) { + return@apply + } + + id() + 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 = (if (id.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Brand && + id == other.id && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Brand{id=$id, additionalProperties=$additionalProperties}" + } + + class Content + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val elements: JsonField>, + private val version: JsonField, + private val scope: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("elements") + @ExcludeMissing + elements: JsonField> = JsonMissing.of(), + @JsonProperty("version") @ExcludeMissing version: JsonField = JsonMissing.of(), + @JsonProperty("scope") @ExcludeMissing scope: JsonField = JsonMissing.of(), + ) : this(elements, version, scope, 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). + */ + fun elements(): List = elements.getRequired("elements") + + /** + * @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 version(): Version = version.getRequired("version") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun scope(): Optional = scope.getOptional("scope") + + /** + * Returns the raw JSON value of [elements]. + * + * Unlike [elements], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("elements") + @ExcludeMissing + fun _elements(): JsonField> = elements + + /** + * Returns the raw JSON value of [version]. + * + * Unlike [version], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version + + /** + * Returns the raw JSON value of [scope]. + * + * Unlike [scope], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("scope") @ExcludeMissing fun _scope(): JsonField = scope + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Content]. + * + * The following fields are required: + * ```java + * .elements() + * .version() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Content]. */ + class Builder internal constructor() { + + private var elements: JsonField>? = null + private var version: JsonField? = null + private var scope: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(content: Content) = apply { + elements = content.elements.map { it.toMutableList() } + version = content.version + scope = content.scope + additionalProperties = content.additionalProperties.toMutableMap() + } + + fun elements(elements: List) = elements(JsonField.of(elements)) + + /** + * Sets [Builder.elements] to an arbitrary JSON value. + * + * You should usually call [Builder.elements] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun elements(elements: JsonField>) = apply { + this.elements = elements.map { it.toMutableList() } + } + + /** + * Adds a single [ElementalNode] to [elements]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addElement(element: ElementalNode) = apply { + elements = + (elements ?: JsonField.of(mutableListOf())).also { + checkKnown("elements", it).add(element) + } + } + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofTextNodeWithType(textNodeWithType)`. + */ + fun addElement(textNodeWithType: ElementalTextNodeWithType) = + addElement(ElementalNode.ofTextNodeWithType(textNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofMetaNodeWithType(metaNodeWithType)`. + */ + fun addElement(metaNodeWithType: ElementalMetaNodeWithType) = + addElement(ElementalNode.ofMetaNodeWithType(metaNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofChannelNodeWithType(channelNodeWithType)`. + */ + fun addElement(channelNodeWithType: ElementalChannelNodeWithType) = + addElement(ElementalNode.ofChannelNodeWithType(channelNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofImageNodeWithType(imageNodeWithType)`. + */ + fun addElement(imageNodeWithType: ElementalImageNodeWithType) = + addElement(ElementalNode.ofImageNodeWithType(imageNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofActionNodeWithType(actionNodeWithType)`. + */ + fun addElement(actionNodeWithType: ElementalActionNodeWithType) = + addElement(ElementalNode.ofActionNodeWithType(actionNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofDividerNodeWithType(dividerNodeWithType)`. + */ + fun addElement(dividerNodeWithType: ElementalDividerNodeWithType) = + addElement(ElementalNode.ofDividerNodeWithType(dividerNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofQuoteNodeWithType(quoteNodeWithType)`. + */ + fun addElement(quoteNodeWithType: ElementalQuoteNodeWithType) = + addElement(ElementalNode.ofQuoteNodeWithType(quoteNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofHtmlNodeWithType(htmlNodeWithType)`. + */ + fun addElement(htmlNodeWithType: ElementalHtmlNodeWithType) = + addElement(ElementalNode.ofHtmlNodeWithType(htmlNodeWithType)) + + fun version(version: Version) = version(JsonField.of(version)) + + /** + * Sets [Builder.version] to an arbitrary JSON value. + * + * You should usually call [Builder.version] with a well-typed [Version] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun version(version: JsonField) = apply { this.version = version } + + fun scope(scope: Scope) = scope(JsonField.of(scope)) + + /** + * Sets [Builder.scope] to an arbitrary JSON value. + * + * You should usually call [Builder.scope] with a well-typed [Scope] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun scope(scope: JsonField) = apply { this.scope = scope } + + fun 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 [Content]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .elements() + * .version() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Content = + Content( + checkRequired("elements", elements).map { it.toImmutable() }, + checkRequired("version", version), + scope, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Content = apply { + if (validated) { + return@apply + } + + elements().forEach { it.validate() } + version().validate() + scope().ifPresent { it.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 = + (elements.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (version.asKnown().getOrNull()?.validity() ?: 0) + + (scope.asKnown().getOrNull()?.validity() ?: 0) + + class Version @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _2022_01_01 = of("2022-01-01") + + @JvmStatic fun of(value: String) = Version(JsonField.of(value)) + } + + /** An enum containing [Version]'s known values. */ + enum class Known { + _2022_01_01 + } + + /** + * An enum containing [Version]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Version] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _2022_01_01, + /** + * An enum member indicating that [Version] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _2022_01_01 -> Value._2022_01_01 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + _2022_01_01 -> Known._2022_01_01 + else -> throw CourierInvalidDataException("Unknown Version: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CourierInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Version = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Version && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Scope @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DEFAULT = of("default") + + @JvmField val STRICT = of("strict") + + @JvmStatic fun of(value: String) = Scope(JsonField.of(value)) + } + + /** An enum containing [Scope]'s known values. */ + enum class Known { + DEFAULT, + STRICT, + } + + /** + * An enum containing [Scope]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Scope] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DEFAULT, + STRICT, + /** + * An enum member indicating that [Scope] was instantiated with an unknown value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you + * want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DEFAULT -> Value.DEFAULT + STRICT -> Value.STRICT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + DEFAULT -> Known.DEFAULT + STRICT -> Known.STRICT + else -> throw CourierInvalidDataException("Unknown Scope: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CourierInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Scope = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Scope && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Content && + elements == other.elements && + version == other.version && + scope == other.scope && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(elements, version, scope, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Content{elements=$elements, version=$version, scope=$scope, additionalProperties=$additionalProperties}" + } + + class State @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DRAFT = of("DRAFT") + + @JvmField val PUBLISHED = of("PUBLISHED") + + @JvmStatic fun of(value: String) = State(JsonField.of(value)) + } + + /** An enum containing [State]'s known values. */ + enum class Known { + DRAFT, + PUBLISHED, + } + + /** + * An enum containing [State]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [State] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DRAFT, + PUBLISHED, + /** An enum member indicating that [State] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DRAFT -> Value.DRAFT + PUBLISHED -> Value.PUBLISHED + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + DRAFT -> Known.DRAFT + PUBLISHED -> Known.PUBLISHED + else -> throw CourierInvalidDataException("Unknown State: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): State = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is State && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Subscription + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val topicId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("topic_id") @ExcludeMissing topicId: JsonField = JsonMissing.of() + ) : this(topicId, 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). + */ + fun topicId(): String = topicId.getRequired("topic_id") + + /** + * Returns the raw JSON value of [topicId]. + * + * Unlike [topicId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("topic_id") @ExcludeMissing fun _topicId(): JsonField = topicId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Subscription]. + * + * The following fields are required: + * ```java + * .topicId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Subscription]. */ + class Builder internal constructor() { + + private var topicId: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(subscription: Subscription) = apply { + topicId = subscription.topicId + additionalProperties = subscription.additionalProperties.toMutableMap() + } + + fun topicId(topicId: String) = topicId(JsonField.of(topicId)) + + /** + * Sets [Builder.topicId] to an arbitrary JSON value. + * + * You should usually call [Builder.topicId] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun topicId(topicId: JsonField) = apply { this.topicId = topicId } + + 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 [Subscription]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .topicId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Subscription = + Subscription(checkRequired("topicId", topicId), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Subscription = apply { + if (validated) { + return@apply + } + + topicId() + 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 = (if (topicId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Subscription && + topicId == other.topicId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(topicId, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Subscription{topicId=$topicId, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyTemplateGetResponse && + id == other.id && + brand == other.brand && + content == other.content && + created == other.created && + creator == other.creator && + name == other.name && + state == other.state && + subscription == other.subscription && + tags == other.tags && + updated == other.updated && + updater == other.updater && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + id, + brand, + content, + created, + creator, + name, + state, + subscription, + tags, + updated, + updater, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyTemplateGetResponse{id=$id, brand=$brand, content=$content, created=$created, creator=$creator, name=$name, state=$state, subscription=$subscription, tags=$tags, updated=$updated, updater=$updater, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateListResponse.kt new file mode 100644 index 00000000..7d35ffeb --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateListResponse.kt @@ -0,0 +1,237 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.courier.models.Paging +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +/** Paged list of journey-scoped notification templates. */ +class JourneyTemplateListResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val paging: JsonField, + private val results: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("paging") @ExcludeMissing paging: JsonField = JsonMissing.of(), + @JsonProperty("results") + @ExcludeMissing + results: JsonField> = JsonMissing.of(), + ) : this(paging, results, 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). + */ + fun paging(): Paging = paging.getRequired("paging") + + /** + * @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 results(): List = results.getRequired("results") + + /** + * Returns the raw JSON value of [paging]. + * + * Unlike [paging], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("paging") @ExcludeMissing fun _paging(): JsonField = paging + + /** + * Returns the raw JSON value of [results]. + * + * Unlike [results], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("results") + @ExcludeMissing + fun _results(): JsonField> = results + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyTemplateListResponse]. + * + * The following fields are required: + * ```java + * .paging() + * .results() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyTemplateListResponse]. */ + class Builder internal constructor() { + + private var paging: JsonField? = null + private var results: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyTemplateListResponse: JourneyTemplateListResponse) = apply { + paging = journeyTemplateListResponse.paging + results = journeyTemplateListResponse.results.map { it.toMutableList() } + additionalProperties = journeyTemplateListResponse.additionalProperties.toMutableMap() + } + + fun paging(paging: Paging) = paging(JsonField.of(paging)) + + /** + * Sets [Builder.paging] to an arbitrary JSON value. + * + * You should usually call [Builder.paging] with a well-typed [Paging] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun paging(paging: JsonField) = apply { this.paging = paging } + + fun results(results: List) = results(JsonField.of(results)) + + /** + * Sets [Builder.results] to an arbitrary JSON value. + * + * You should usually call [Builder.results] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun results(results: JsonField>) = apply { + this.results = results.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyTemplateSummary] to [results]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addResult(result: JourneyTemplateSummary) = apply { + results = + (results ?: JsonField.of(mutableListOf())).also { + checkKnown("results", it).add(result) + } + } + + 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 [JourneyTemplateListResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .paging() + * .results() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyTemplateListResponse = + JourneyTemplateListResponse( + checkRequired("paging", paging), + checkRequired("results", results).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyTemplateListResponse = apply { + if (validated) { + return@apply + } + + paging().validate() + results().forEach { it.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 = + (paging.asKnown().getOrNull()?.validity() ?: 0) + + (results.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyTemplateListResponse && + paging == other.paging && + results == other.results && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(paging, results, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyTemplateListResponse{paging=$paging, results=$results, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplatePublishRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplatePublishRequest.kt new file mode 100644 index 00000000..22fecdbe --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplatePublishRequest.kt @@ -0,0 +1,168 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional + +/** + * Request body for publishing a journey-scoped notification template. Pass `version` to roll back + * to a prior version; omit to publish the current draft. + */ +class JourneyTemplatePublishRequest +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val version: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("version") @ExcludeMissing version: JsonField = JsonMissing.of() + ) : this(version, mutableMapOf()) + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun version(): Optional = version.getOptional("version") + + /** + * Returns the raw JSON value of [version]. + * + * Unlike [version], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [JourneyTemplatePublishRequest]. + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyTemplatePublishRequest]. */ + class Builder internal constructor() { + + private var version: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyTemplatePublishRequest: JourneyTemplatePublishRequest) = apply { + version = journeyTemplatePublishRequest.version + additionalProperties = journeyTemplatePublishRequest.additionalProperties.toMutableMap() + } + + fun version(version: String) = version(JsonField.of(version)) + + /** + * Sets [Builder.version] to an arbitrary JSON value. + * + * You should usually call [Builder.version] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun version(version: JsonField) = apply { this.version = version } + + 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 [JourneyTemplatePublishRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): JourneyTemplatePublishRequest = + JourneyTemplatePublishRequest(version, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyTemplatePublishRequest = apply { + if (validated) { + return@apply + } + + version() + 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 = (if (version.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyTemplatePublishRequest && + version == other.version && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(version, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyTemplatePublishRequest{version=$version, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateReplaceRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateReplaceRequest.kt new file mode 100644 index 00000000..8883789a --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateReplaceRequest.kt @@ -0,0 +1,1498 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.courier.models.ElementalActionNodeWithType +import com.courier.models.ElementalChannelNodeWithType +import com.courier.models.ElementalDividerNodeWithType +import com.courier.models.ElementalHtmlNodeWithType +import com.courier.models.ElementalImageNodeWithType +import com.courier.models.ElementalMetaNodeWithType +import com.courier.models.ElementalNode +import com.courier.models.ElementalQuoteNodeWithType +import com.courier.models.ElementalTextNodeWithType +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Request body for replacing a journey-scoped notification template draft. */ +class JourneyTemplateReplaceRequest +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val notification: JsonField, + private val state: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("notification") + @ExcludeMissing + notification: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + ) : this(notification, state, 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). + */ + fun notification(): Notification = notification.getRequired("notification") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun state(): Optional = state.getOptional("state") + + /** + * Returns the raw JSON value of [notification]. + * + * Unlike [notification], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("notification") + @ExcludeMissing + fun _notification(): JsonField = notification + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [JourneyTemplateReplaceRequest]. + * + * The following fields are required: + * ```java + * .notification() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyTemplateReplaceRequest]. */ + class Builder internal constructor() { + + private var notification: JsonField? = null + private var state: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyTemplateReplaceRequest: JourneyTemplateReplaceRequest) = apply { + notification = journeyTemplateReplaceRequest.notification + state = journeyTemplateReplaceRequest.state + additionalProperties = journeyTemplateReplaceRequest.additionalProperties.toMutableMap() + } + + fun notification(notification: Notification) = notification(JsonField.of(notification)) + + /** + * Sets [Builder.notification] to an arbitrary JSON value. + * + * You should usually call [Builder.notification] with a well-typed [Notification] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun notification(notification: JsonField) = apply { + this.notification = notification + } + + fun state(state: String) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun state(state: JsonField) = apply { this.state = state } + + 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 [JourneyTemplateReplaceRequest]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .notification() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyTemplateReplaceRequest = + JourneyTemplateReplaceRequest( + checkRequired("notification", notification), + state, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyTemplateReplaceRequest = apply { + if (validated) { + return@apply + } + + notification().validate() + state() + 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 = + (notification.asKnown().getOrNull()?.validity() ?: 0) + + (if (state.asKnown().isPresent) 1 else 0) + + class Notification + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val brand: JsonField, + private val content: JsonField, + private val name: JsonField, + private val subscription: JsonField, + private val tags: JsonField>, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("brand") @ExcludeMissing brand: JsonField = JsonMissing.of(), + @JsonProperty("content") @ExcludeMissing content: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("subscription") + @ExcludeMissing + subscription: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + ) : this(brand, content, name, subscription, tags, mutableMapOf()) + + /** + * @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 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 or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun subscription(): Optional = subscription.getOptional("subscription") + + /** + * @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 tags(): List = tags.getRequired("tags") + + /** + * 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 [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 [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [subscription]. + * + * Unlike [subscription], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("subscription") + @ExcludeMissing + fun _subscription(): JsonField = subscription + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Notification]. + * + * The following fields are required: + * ```java + * .brand() + * .content() + * .name() + * .subscription() + * .tags() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Notification]. */ + class Builder internal constructor() { + + private var brand: JsonField? = null + private var content: JsonField? = null + private var name: JsonField? = null + private var subscription: JsonField? = null + private var tags: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(notification: Notification) = apply { + brand = notification.brand + content = notification.content + name = notification.name + subscription = notification.subscription + tags = notification.tags.map { it.toMutableList() } + additionalProperties = notification.additionalProperties.toMutableMap() + } + + fun brand(brand: Brand?) = 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 [Brand] 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 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 } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun subscription(subscription: Subscription?) = + subscription(JsonField.ofNullable(subscription)) + + /** Alias for calling [Builder.subscription] with `subscription.orElse(null)`. */ + fun subscription(subscription: Optional) = + subscription(subscription.getOrNull()) + + /** + * Sets [Builder.subscription] to an arbitrary JSON value. + * + * You should usually call [Builder.subscription] with a well-typed [Subscription] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun subscription(subscription: JsonField) = apply { + this.subscription = subscription + } + + fun tags(tags: List) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun tags(tags: JsonField>) = apply { + this.tags = tags.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: String) = apply { + tags = + (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + 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 [Notification]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .brand() + * .content() + * .name() + * .subscription() + * .tags() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Notification = + Notification( + checkRequired("brand", brand), + checkRequired("content", content), + checkRequired("name", name), + checkRequired("subscription", subscription), + checkRequired("tags", tags).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Notification = apply { + if (validated) { + return@apply + } + + brand().ifPresent { it.validate() } + content().validate() + name() + subscription().ifPresent { it.validate() } + tags() + 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 = + (brand.asKnown().getOrNull()?.validity() ?: 0) + + (content.asKnown().getOrNull()?.validity() ?: 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (subscription.asKnown().getOrNull()?.validity() ?: 0) + + (tags.asKnown().getOrNull()?.size ?: 0) + + class Brand + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val id: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of() + ) : this(id, 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). + */ + fun id(): String = id.getRequired("id") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Brand]. + * + * The following fields are required: + * ```java + * .id() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Brand]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(brand: Brand) = apply { + id = brand.id + additionalProperties = brand.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + 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 [Brand]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Brand = + Brand(checkRequired("id", id), additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Brand = apply { + if (validated) { + return@apply + } + + id() + 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 = (if (id.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Brand && + id == other.id && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = "Brand{id=$id, additionalProperties=$additionalProperties}" + } + + class Content + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val elements: JsonField>, + private val version: JsonField, + private val scope: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("elements") + @ExcludeMissing + elements: JsonField> = JsonMissing.of(), + @JsonProperty("version") + @ExcludeMissing + version: JsonField = JsonMissing.of(), + @JsonProperty("scope") @ExcludeMissing scope: JsonField = JsonMissing.of(), + ) : this(elements, version, scope, 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). + */ + fun elements(): List = elements.getRequired("elements") + + /** + * @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 version(): Version = version.getRequired("version") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun scope(): Optional = scope.getOptional("scope") + + /** + * Returns the raw JSON value of [elements]. + * + * Unlike [elements], this method doesn't throw if the JSON field has an unexpected + * type. + */ + @JsonProperty("elements") + @ExcludeMissing + fun _elements(): JsonField> = elements + + /** + * Returns the raw JSON value of [version]. + * + * Unlike [version], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version + + /** + * Returns the raw JSON value of [scope]. + * + * Unlike [scope], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("scope") @ExcludeMissing fun _scope(): JsonField = scope + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Content]. + * + * The following fields are required: + * ```java + * .elements() + * .version() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Content]. */ + class Builder internal constructor() { + + private var elements: JsonField>? = null + private var version: JsonField? = null + private var scope: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(content: Content) = apply { + elements = content.elements.map { it.toMutableList() } + version = content.version + scope = content.scope + additionalProperties = content.additionalProperties.toMutableMap() + } + + fun elements(elements: List) = elements(JsonField.of(elements)) + + /** + * Sets [Builder.elements] to an arbitrary JSON value. + * + * You should usually call [Builder.elements] with a well-typed + * `List` value instead. This method is primarily for setting the + * field to an undocumented or not yet supported value. + */ + fun elements(elements: JsonField>) = apply { + this.elements = elements.map { it.toMutableList() } + } + + /** + * Adds a single [ElementalNode] to [elements]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addElement(element: ElementalNode) = apply { + elements = + (elements ?: JsonField.of(mutableListOf())).also { + checkKnown("elements", it).add(element) + } + } + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofTextNodeWithType(textNodeWithType)`. + */ + fun addElement(textNodeWithType: ElementalTextNodeWithType) = + addElement(ElementalNode.ofTextNodeWithType(textNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofMetaNodeWithType(metaNodeWithType)`. + */ + fun addElement(metaNodeWithType: ElementalMetaNodeWithType) = + addElement(ElementalNode.ofMetaNodeWithType(metaNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofChannelNodeWithType(channelNodeWithType)`. + */ + fun addElement(channelNodeWithType: ElementalChannelNodeWithType) = + addElement(ElementalNode.ofChannelNodeWithType(channelNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofImageNodeWithType(imageNodeWithType)`. + */ + fun addElement(imageNodeWithType: ElementalImageNodeWithType) = + addElement(ElementalNode.ofImageNodeWithType(imageNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofActionNodeWithType(actionNodeWithType)`. + */ + fun addElement(actionNodeWithType: ElementalActionNodeWithType) = + addElement(ElementalNode.ofActionNodeWithType(actionNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofDividerNodeWithType(dividerNodeWithType)`. + */ + fun addElement(dividerNodeWithType: ElementalDividerNodeWithType) = + addElement(ElementalNode.ofDividerNodeWithType(dividerNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofQuoteNodeWithType(quoteNodeWithType)`. + */ + fun addElement(quoteNodeWithType: ElementalQuoteNodeWithType) = + addElement(ElementalNode.ofQuoteNodeWithType(quoteNodeWithType)) + + /** + * Alias for calling [addElement] with + * `ElementalNode.ofHtmlNodeWithType(htmlNodeWithType)`. + */ + fun addElement(htmlNodeWithType: ElementalHtmlNodeWithType) = + addElement(ElementalNode.ofHtmlNodeWithType(htmlNodeWithType)) + + fun version(version: Version) = version(JsonField.of(version)) + + /** + * Sets [Builder.version] to an arbitrary JSON value. + * + * You should usually call [Builder.version] with a well-typed [Version] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun version(version: JsonField) = apply { this.version = version } + + fun scope(scope: Scope) = scope(JsonField.of(scope)) + + /** + * Sets [Builder.scope] to an arbitrary JSON value. + * + * You should usually call [Builder.scope] with a well-typed [Scope] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun scope(scope: JsonField) = apply { this.scope = scope } + + fun 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 [Content]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .elements() + * .version() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Content = + Content( + checkRequired("elements", elements).map { it.toImmutable() }, + checkRequired("version", version), + scope, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Content = apply { + if (validated) { + return@apply + } + + elements().forEach { it.validate() } + version().validate() + scope().ifPresent { it.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 = + (elements.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (version.asKnown().getOrNull()?.validity() ?: 0) + + (scope.asKnown().getOrNull()?.validity() ?: 0) + + class Version @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val _2022_01_01 = of("2022-01-01") + + @JvmStatic fun of(value: String) = Version(JsonField.of(value)) + } + + /** An enum containing [Version]'s known values. */ + enum class Known { + _2022_01_01 + } + + /** + * An enum containing [Version]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Version] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + _2022_01_01, + /** + * An enum member indicating that [Version] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + _2022_01_01 -> Value._2022_01_01 + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + _2022_01_01 -> Known._2022_01_01 + else -> throw CourierInvalidDataException("Unknown Version: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CourierInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): Version = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Version && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Scope @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that + * doesn't match any known member, and you want to know that value. For example, if + * the SDK is on an older version than the API, then the API may respond with new + * members that the SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DEFAULT = of("default") + + @JvmField val STRICT = of("strict") + + @JvmStatic fun of(value: String) = Scope(JsonField.of(value)) + } + + /** An enum containing [Scope]'s known values. */ + enum class Known { + DEFAULT, + STRICT, + } + + /** + * An enum containing [Scope]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Scope] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, + * if the SDK is on an older version than the API, then the API may respond with + * new members that the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DEFAULT, + STRICT, + /** + * An enum member indicating that [Scope] was instantiated with an unknown + * value. + */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or + * [Value._UNKNOWN] if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if + * you want to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DEFAULT -> Value.DEFAULT + STRICT -> Value.STRICT + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and + * don't want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a + * known member. + */ + fun known(): Known = + when (this) { + DEFAULT -> Known.DEFAULT + STRICT -> Known.STRICT + else -> throw CourierInvalidDataException("Unknown Scope: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for + * debugging and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have + * the expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + CourierInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): Scope = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Scope && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Content && + elements == other.elements && + version == other.version && + scope == other.scope && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(elements, version, scope, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Content{elements=$elements, version=$version, scope=$scope, additionalProperties=$additionalProperties}" + } + + class Subscription + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val topicId: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("topic_id") + @ExcludeMissing + topicId: JsonField = JsonMissing.of() + ) : this(topicId, 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). + */ + fun topicId(): String = topicId.getRequired("topic_id") + + /** + * Returns the raw JSON value of [topicId]. + * + * Unlike [topicId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("topic_id") @ExcludeMissing fun _topicId(): JsonField = topicId + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Subscription]. + * + * The following fields are required: + * ```java + * .topicId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Subscription]. */ + class Builder internal constructor() { + + private var topicId: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(subscription: Subscription) = apply { + topicId = subscription.topicId + additionalProperties = subscription.additionalProperties.toMutableMap() + } + + fun topicId(topicId: String) = topicId(JsonField.of(topicId)) + + /** + * Sets [Builder.topicId] to an arbitrary JSON value. + * + * You should usually call [Builder.topicId] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun topicId(topicId: JsonField) = apply { this.topicId = topicId } + + 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 [Subscription]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .topicId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Subscription = + Subscription( + checkRequired("topicId", topicId), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ + fun validate(): Subscription = apply { + if (validated) { + return@apply + } + + topicId() + 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 = (if (topicId.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Subscription && + topicId == other.topicId && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(topicId, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Subscription{topicId=$topicId, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Notification && + brand == other.brand && + content == other.content && + name == other.name && + subscription == other.subscription && + tags == other.tags && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(brand, content, name, subscription, tags, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Notification{brand=$brand, content=$content, name=$name, subscription=$subscription, tags=$tags, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyTemplateReplaceRequest && + notification == other.notification && + state == other.state && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(notification, state, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyTemplateReplaceRequest{notification=$notification, state=$state, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateSummary.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateSummary.kt new file mode 100644 index 00000000..a2b71f90 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyTemplateSummary.kt @@ -0,0 +1,436 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Summary fields of a journey-scoped notification template returned in list responses. */ +class JourneyTemplateSummary +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val created: JsonField, + private val creator: JsonField, + private val name: JsonField, + private val state: JsonField, + private val tags: JsonField>, + private val updated: JsonField, + private val updater: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("created") @ExcludeMissing created: JsonField = JsonMissing.of(), + @JsonProperty("creator") @ExcludeMissing creator: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("state") @ExcludeMissing state: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + @JsonProperty("updated") @ExcludeMissing updated: JsonField = JsonMissing.of(), + @JsonProperty("updater") @ExcludeMissing updater: JsonField = JsonMissing.of(), + ) : this(id, created, creator, name, state, tags, updated, updater, 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). + */ + fun id(): String = id.getRequired("id") + + /** + * @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 created(): Long = created.getRequired("created") + + /** + * @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 creator(): String = creator.getRequired("creator") + + /** + * @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 name(): String = name.getRequired("name") + + /** + * @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 state(): String = state.getRequired("state") + + /** + * @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 tags(): List = tags.getRequired("tags") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun updated(): Optional = updated.getOptional("updated") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun updater(): Optional = updater.getOptional("updater") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * Returns the raw JSON value of [creator]. + * + * Unlike [creator], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("creator") @ExcludeMissing fun _creator(): JsonField = creator + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [state]. + * + * Unlike [state], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("state") @ExcludeMissing fun _state(): JsonField = state + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags + + /** + * Returns the raw JSON value of [updated]. + * + * Unlike [updated], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updated") @ExcludeMissing fun _updated(): JsonField = updated + + /** + * Returns the raw JSON value of [updater]. + * + * Unlike [updater], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updater") @ExcludeMissing fun _updater(): JsonField = updater + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyTemplateSummary]. + * + * The following fields are required: + * ```java + * .id() + * .created() + * .creator() + * .name() + * .state() + * .tags() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyTemplateSummary]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var created: JsonField? = null + private var creator: JsonField? = null + private var name: JsonField? = null + private var state: JsonField? = null + private var tags: JsonField>? = null + private var updated: JsonField = JsonMissing.of() + private var updater: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyTemplateSummary: JourneyTemplateSummary) = apply { + id = journeyTemplateSummary.id + created = journeyTemplateSummary.created + creator = journeyTemplateSummary.creator + name = journeyTemplateSummary.name + state = journeyTemplateSummary.state + tags = journeyTemplateSummary.tags.map { it.toMutableList() } + updated = journeyTemplateSummary.updated + updater = journeyTemplateSummary.updater + additionalProperties = journeyTemplateSummary.additionalProperties.toMutableMap() + } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun created(created: Long) = created(JsonField.of(created)) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + fun creator(creator: String) = creator(JsonField.of(creator)) + + /** + * Sets [Builder.creator] to an arbitrary JSON value. + * + * You should usually call [Builder.creator] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun creator(creator: JsonField) = apply { this.creator = creator } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun state(state: String) = state(JsonField.of(state)) + + /** + * Sets [Builder.state] to an arbitrary JSON value. + * + * You should usually call [Builder.state] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun state(state: JsonField) = apply { this.state = state } + + fun tags(tags: List) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun tags(tags: JsonField>) = apply { + this.tags = tags.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: String) = apply { + tags = (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + fun updated(updated: Long) = updated(JsonField.of(updated)) + + /** + * Sets [Builder.updated] to an arbitrary JSON value. + * + * You should usually call [Builder.updated] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun updated(updated: JsonField) = apply { this.updated = updated } + + fun updater(updater: String) = updater(JsonField.of(updater)) + + /** + * Sets [Builder.updater] to an arbitrary JSON value. + * + * You should usually call [Builder.updater] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun updater(updater: JsonField) = apply { this.updater = updater } + + 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 [JourneyTemplateSummary]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .id() + * .created() + * .creator() + * .name() + * .state() + * .tags() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyTemplateSummary = + JourneyTemplateSummary( + checkRequired("id", id), + checkRequired("created", created), + checkRequired("creator", creator), + checkRequired("name", name), + checkRequired("state", state), + checkRequired("tags", tags).map { it.toImmutable() }, + updated, + updater, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyTemplateSummary = apply { + if (validated) { + return@apply + } + + id() + created() + creator() + name() + state() + tags() + updated() + updater() + 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 = + (if (id.asKnown().isPresent) 1 else 0) + + (if (created.asKnown().isPresent) 1 else 0) + + (if (creator.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (state.asKnown().isPresent) 1 else 0) + + (tags.asKnown().getOrNull()?.size ?: 0) + + (if (updated.asKnown().isPresent) 1 else 0) + + (if (updater.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyTemplateSummary && + id == other.id && + created == other.created && + creator == other.creator && + name == other.name && + state == other.state && + tags == other.tags && + updated == other.updated && + updater == other.updater && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + id, + created, + creator, + name, + state, + tags, + updated, + updater, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyTemplateSummary{id=$id, created=$created, creator=$creator, name=$name, state=$state, tags=$tags, updated=$updated, updater=$updater, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyThrottleDynamicNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyThrottleDynamicNode.kt new file mode 100644 index 00000000..73a5aaa4 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyThrottleDynamicNode.kt @@ -0,0 +1,689 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Throttle the journey by a dynamic `throttle_key`, allowing at most `max_allowed` invocations per + * `period`. + */ +class JourneyThrottleDynamicNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val maxAllowed: JsonField, + private val period: JsonField, + private val scope: JsonField, + private val throttleKey: JsonField, + private val type: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("max_allowed") @ExcludeMissing maxAllowed: JsonField = JsonMissing.of(), + @JsonProperty("period") @ExcludeMissing period: JsonField = JsonMissing.of(), + @JsonProperty("scope") @ExcludeMissing scope: JsonField = JsonMissing.of(), + @JsonProperty("throttle_key") + @ExcludeMissing + throttleKey: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + ) : this(maxAllowed, period, scope, throttleKey, type, id, conditions, 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). + */ + fun maxAllowed(): Long = maxAllowed.getRequired("max_allowed") + + /** + * @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 period(): String = period.getRequired("period") + + /** + * @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 scope(): Scope = scope.getRequired("scope") + + /** + * @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 throttleKey(): String = throttleKey.getRequired("throttle_key") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * Returns the raw JSON value of [maxAllowed]. + * + * Unlike [maxAllowed], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("max_allowed") @ExcludeMissing fun _maxAllowed(): JsonField = maxAllowed + + /** + * Returns the raw JSON value of [period]. + * + * Unlike [period], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("period") @ExcludeMissing fun _period(): JsonField = period + + /** + * Returns the raw JSON value of [scope]. + * + * Unlike [scope], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("scope") @ExcludeMissing fun _scope(): JsonField = scope + + /** + * Returns the raw JSON value of [throttleKey]. + * + * Unlike [throttleKey], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("throttle_key") + @ExcludeMissing + fun _throttleKey(): JsonField = throttleKey + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyThrottleDynamicNode]. + * + * The following fields are required: + * ```java + * .maxAllowed() + * .period() + * .scope() + * .throttleKey() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyThrottleDynamicNode]. */ + class Builder internal constructor() { + + private var maxAllowed: JsonField? = null + private var period: JsonField? = null + private var scope: JsonField? = null + private var throttleKey: JsonField? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyThrottleDynamicNode: JourneyThrottleDynamicNode) = apply { + maxAllowed = journeyThrottleDynamicNode.maxAllowed + period = journeyThrottleDynamicNode.period + scope = journeyThrottleDynamicNode.scope + throttleKey = journeyThrottleDynamicNode.throttleKey + type = journeyThrottleDynamicNode.type + id = journeyThrottleDynamicNode.id + conditions = journeyThrottleDynamicNode.conditions + additionalProperties = journeyThrottleDynamicNode.additionalProperties.toMutableMap() + } + + fun maxAllowed(maxAllowed: Long) = maxAllowed(JsonField.of(maxAllowed)) + + /** + * Sets [Builder.maxAllowed] to an arbitrary JSON value. + * + * You should usually call [Builder.maxAllowed] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun maxAllowed(maxAllowed: JsonField) = apply { this.maxAllowed = maxAllowed } + + fun period(period: String) = period(JsonField.of(period)) + + /** + * Sets [Builder.period] to an arbitrary JSON value. + * + * You should usually call [Builder.period] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun period(period: JsonField) = apply { this.period = period } + + fun scope(scope: Scope) = scope(JsonField.of(scope)) + + /** + * Sets [Builder.scope] to an arbitrary JSON value. + * + * You should usually call [Builder.scope] with a well-typed [Scope] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun scope(scope: JsonField) = apply { this.scope = scope } + + fun throttleKey(throttleKey: String) = throttleKey(JsonField.of(throttleKey)) + + /** + * Sets [Builder.throttleKey] to an arbitrary JSON value. + * + * You should usually call [Builder.throttleKey] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun throttleKey(throttleKey: JsonField) = apply { this.throttleKey = throttleKey } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + 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 [JourneyThrottleDynamicNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .maxAllowed() + * .period() + * .scope() + * .throttleKey() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyThrottleDynamicNode = + JourneyThrottleDynamicNode( + checkRequired("maxAllowed", maxAllowed), + checkRequired("period", period), + checkRequired("scope", scope), + checkRequired("throttleKey", throttleKey), + checkRequired("type", type), + id, + conditions, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyThrottleDynamicNode = apply { + if (validated) { + return@apply + } + + maxAllowed() + period() + scope().validate() + throttleKey() + type().validate() + id() + conditions().ifPresent { it.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 = + (if (maxAllowed.asKnown().isPresent) 1 else 0) + + (if (period.asKnown().isPresent) 1 else 0) + + (scope.asKnown().getOrNull()?.validity() ?: 0) + + (if (throttleKey.asKnown().isPresent) 1 else 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + class Scope @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val DYNAMIC = of("dynamic") + + @JvmStatic fun of(value: String) = Scope(JsonField.of(value)) + } + + /** An enum containing [Scope]'s known values. */ + enum class Known { + DYNAMIC + } + + /** + * An enum containing [Scope]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Scope] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + DYNAMIC, + /** An enum member indicating that [Scope] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + DYNAMIC -> Value.DYNAMIC + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + DYNAMIC -> Known.DYNAMIC + else -> throw CourierInvalidDataException("Unknown Scope: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Scope = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Scope && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val THROTTLE = of("throttle") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + THROTTLE + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + THROTTLE, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + THROTTLE -> Value.THROTTLE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + THROTTLE -> Known.THROTTLE + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyThrottleDynamicNode && + maxAllowed == other.maxAllowed && + period == other.period && + scope == other.scope && + throttleKey == other.throttleKey && + type == other.type && + id == other.id && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + maxAllowed, + period, + scope, + throttleKey, + type, + id, + conditions, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyThrottleDynamicNode{maxAllowed=$maxAllowed, period=$period, scope=$scope, throttleKey=$throttleKey, type=$type, id=$id, conditions=$conditions, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyThrottleStaticNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyThrottleStaticNode.kt new file mode 100644 index 00000000..18524b5a --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyThrottleStaticNode.kt @@ -0,0 +1,648 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.Enum +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Throttle the journey by a static `scope` (`user` or `global`), allowing at most `max_allowed` + * invocations per `period`. + */ +class JourneyThrottleStaticNode +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val maxAllowed: JsonField, + private val period: JsonField, + private val scope: JsonField, + private val type: JsonField, + private val id: JsonField, + private val conditions: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("max_allowed") @ExcludeMissing maxAllowed: JsonField = JsonMissing.of(), + @JsonProperty("period") @ExcludeMissing period: JsonField = JsonMissing.of(), + @JsonProperty("scope") @ExcludeMissing scope: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("conditions") + @ExcludeMissing + conditions: JsonField = JsonMissing.of(), + ) : this(maxAllowed, period, scope, type, id, conditions, 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). + */ + fun maxAllowed(): Long = maxAllowed.getRequired("max_allowed") + + /** + * @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 period(): String = period.getRequired("period") + + /** + * @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 scope(): Scope = scope.getRequired("scope") + + /** + * @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 type(): Type = type.getRequired("type") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun id(): Optional = id.getOptional("id") + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or an + * AND/OR nested group. Omit the `conditions` property entirely to express "no conditions". + * + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun conditions(): Optional = conditions.getOptional("conditions") + + /** + * Returns the raw JSON value of [maxAllowed]. + * + * Unlike [maxAllowed], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("max_allowed") @ExcludeMissing fun _maxAllowed(): JsonField = maxAllowed + + /** + * Returns the raw JSON value of [period]. + * + * Unlike [period], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("period") @ExcludeMissing fun _period(): JsonField = period + + /** + * Returns the raw JSON value of [scope]. + * + * Unlike [scope], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("scope") @ExcludeMissing fun _scope(): JsonField = scope + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [conditions]. + * + * Unlike [conditions], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("conditions") + @ExcludeMissing + fun _conditions(): JsonField = conditions + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyThrottleStaticNode]. + * + * The following fields are required: + * ```java + * .maxAllowed() + * .period() + * .scope() + * .type() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyThrottleStaticNode]. */ + class Builder internal constructor() { + + private var maxAllowed: JsonField? = null + private var period: JsonField? = null + private var scope: JsonField? = null + private var type: JsonField? = null + private var id: JsonField = JsonMissing.of() + private var conditions: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyThrottleStaticNode: JourneyThrottleStaticNode) = apply { + maxAllowed = journeyThrottleStaticNode.maxAllowed + period = journeyThrottleStaticNode.period + scope = journeyThrottleStaticNode.scope + type = journeyThrottleStaticNode.type + id = journeyThrottleStaticNode.id + conditions = journeyThrottleStaticNode.conditions + additionalProperties = journeyThrottleStaticNode.additionalProperties.toMutableMap() + } + + fun maxAllowed(maxAllowed: Long) = maxAllowed(JsonField.of(maxAllowed)) + + /** + * Sets [Builder.maxAllowed] to an arbitrary JSON value. + * + * You should usually call [Builder.maxAllowed] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun maxAllowed(maxAllowed: JsonField) = apply { this.maxAllowed = maxAllowed } + + fun period(period: String) = period(JsonField.of(period)) + + /** + * Sets [Builder.period] to an arbitrary JSON value. + * + * You should usually call [Builder.period] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun period(period: JsonField) = apply { this.period = period } + + fun scope(scope: Scope) = scope(JsonField.of(scope)) + + /** + * Sets [Builder.scope] to an arbitrary JSON value. + * + * You should usually call [Builder.scope] with a well-typed [Scope] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun scope(scope: JsonField) = apply { this.scope = scope } + + fun type(type: Type) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [Type] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun id(id: String) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + /** + * Condition spec for a journey node. Accepts a single condition atom, an AND/OR group, or + * an AND/OR nested group. Omit the `conditions` property entirely to express "no + * conditions". + */ + fun conditions(conditions: JourneyConditionsField) = conditions(JsonField.of(conditions)) + + /** + * Sets [Builder.conditions] to an arbitrary JSON value. + * + * You should usually call [Builder.conditions] with a well-typed [JourneyConditionsField] + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun conditions(conditions: JsonField) = apply { + this.conditions = conditions + } + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionAtom(conditionAtom)`. + */ + fun conditionsOfConditionAtom(conditionAtom: List) = + conditions(JourneyConditionsField.ofConditionAtom(conditionAtom)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionGroup(conditionGroup)`. + */ + fun conditions(conditionGroup: JourneyConditionGroup) = + conditions(JourneyConditionsField.ofConditionGroup(conditionGroup)) + + /** + * Alias for calling [conditions] with + * `JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)`. + */ + fun conditions(conditionNestedGroup: JourneyConditionNestedGroup) = + conditions(JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup)) + + 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 [JourneyThrottleStaticNode]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .maxAllowed() + * .period() + * .scope() + * .type() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyThrottleStaticNode = + JourneyThrottleStaticNode( + checkRequired("maxAllowed", maxAllowed), + checkRequired("period", period), + checkRequired("scope", scope), + checkRequired("type", type), + id, + conditions, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyThrottleStaticNode = apply { + if (validated) { + return@apply + } + + maxAllowed() + period() + scope().validate() + type().validate() + id() + conditions().ifPresent { it.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 = + (if (maxAllowed.asKnown().isPresent) 1 else 0) + + (if (period.asKnown().isPresent) 1 else 0) + + (scope.asKnown().getOrNull()?.validity() ?: 0) + + (type.asKnown().getOrNull()?.validity() ?: 0) + + (if (id.asKnown().isPresent) 1 else 0) + + (conditions.asKnown().getOrNull()?.validity() ?: 0) + + class Scope @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val USER = of("user") + + @JvmField val GLOBAL = of("global") + + @JvmStatic fun of(value: String) = Scope(JsonField.of(value)) + } + + /** An enum containing [Scope]'s known values. */ + enum class Known { + USER, + GLOBAL, + } + + /** + * An enum containing [Scope]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Scope] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + USER, + GLOBAL, + /** An enum member indicating that [Scope] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + USER -> Value.USER + GLOBAL -> Value.GLOBAL + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + USER -> Known.USER + GLOBAL -> Known.GLOBAL + else -> throw CourierInvalidDataException("Unknown Scope: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Scope = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Scope && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Type @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val THROTTLE = of("throttle") + + @JvmStatic fun of(value: String) = Type(JsonField.of(value)) + } + + /** An enum containing [Type]'s known values. */ + enum class Known { + THROTTLE + } + + /** + * An enum containing [Type]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Type] can contain an unknown value in a couple of cases: + * - It was deserialized from data that doesn't match any known member. For example, if the + * SDK is on an older version than the API, then the API may respond with new members that + * the SDK is unaware of. + * - It was constructed with an arbitrary value using the [of] method. + */ + enum class Value { + THROTTLE, + /** An enum member indicating that [Type] was instantiated with an unknown value. */ + _UNKNOWN, + } + + /** + * Returns an enum member corresponding to this class instance's value, or [Value._UNKNOWN] + * if the class was instantiated with an unknown value. + * + * Use the [known] method instead if you're certain the value is always known or if you want + * to throw for the unknown case. + */ + fun value(): Value = + when (this) { + THROTTLE -> Value.THROTTLE + else -> Value._UNKNOWN + } + + /** + * Returns an enum member corresponding to this class instance's value. + * + * Use the [value] method instead if you're uncertain the value is always known and don't + * want to throw for the unknown case. + * + * @throws CourierInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + THROTTLE -> Known.THROTTLE + else -> throw CourierInvalidDataException("Unknown Type: $value") + } + + /** + * Returns this class instance's primitive wire representation. + * + * This differs from the [toString] method because that method is primarily for debugging + * and generally doesn't throw. + * + * @throws CourierInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { CourierInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Type = apply { + if (validated) { + return@apply + } + + known() + 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 = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Type && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyThrottleStaticNode && + maxAllowed == other.maxAllowed && + period == other.period && + scope == other.scope && + type == other.type && + id == other.id && + conditions == other.conditions && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(maxAllowed, period, scope, type, id, conditions, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyThrottleStaticNode{maxAllowed=$maxAllowed, period=$period, scope=$scope, type=$type, id=$id, conditions=$conditions, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyVersionItem.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyVersionItem.kt new file mode 100644 index 00000000..9358b2c0 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyVersionItem.kt @@ -0,0 +1,340 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkRequired +import com.courier.errors.CourierInvalidDataException +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** A published version of a journey. */ +class JourneyVersionItem +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val created: JsonField, + private val creator: JsonField, + private val name: JsonField, + private val published: JsonField, + private val version: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("created") @ExcludeMissing created: JsonField = JsonMissing.of(), + @JsonProperty("creator") @ExcludeMissing creator: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("published") @ExcludeMissing published: JsonField = JsonMissing.of(), + @JsonProperty("version") @ExcludeMissing version: JsonField = JsonMissing.of(), + ) : this(created, creator, name, published, version, mutableMapOf()) + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun created(): Optional = created.getOptional("created") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun creator(): Optional = creator.getOptional("creator") + + /** + * @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 name(): String = name.getRequired("name") + + /** + * @throws CourierInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun published(): Optional = published.getOptional("published") + + /** + * @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 version(): String = version.getRequired("version") + + /** + * Returns the raw JSON value of [created]. + * + * Unlike [created], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created + + /** + * Returns the raw JSON value of [creator]. + * + * Unlike [creator], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("creator") @ExcludeMissing fun _creator(): JsonField = creator + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [published]. + * + * Unlike [published], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("published") @ExcludeMissing fun _published(): JsonField = published + + /** + * Returns the raw JSON value of [version]. + * + * Unlike [version], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyVersionItem]. + * + * The following fields are required: + * ```java + * .created() + * .creator() + * .name() + * .published() + * .version() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyVersionItem]. */ + class Builder internal constructor() { + + private var created: JsonField? = null + private var creator: JsonField? = null + private var name: JsonField? = null + private var published: JsonField? = null + private var version: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyVersionItem: JourneyVersionItem) = apply { + created = journeyVersionItem.created + creator = journeyVersionItem.creator + name = journeyVersionItem.name + published = journeyVersionItem.published + version = journeyVersionItem.version + additionalProperties = journeyVersionItem.additionalProperties.toMutableMap() + } + + fun created(created: Long?) = created(JsonField.ofNullable(created)) + + /** + * Alias for [Builder.created]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun created(created: Long) = created(created as Long?) + + /** Alias for calling [Builder.created] with `created.orElse(null)`. */ + fun created(created: Optional) = created(created.getOrNull()) + + /** + * Sets [Builder.created] to an arbitrary JSON value. + * + * You should usually call [Builder.created] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun created(created: JsonField) = apply { this.created = created } + + fun creator(creator: String?) = creator(JsonField.ofNullable(creator)) + + /** Alias for calling [Builder.creator] with `creator.orElse(null)`. */ + fun creator(creator: Optional) = creator(creator.getOrNull()) + + /** + * Sets [Builder.creator] to an arbitrary JSON value. + * + * You should usually call [Builder.creator] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun creator(creator: JsonField) = apply { this.creator = creator } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun published(published: Long?) = published(JsonField.ofNullable(published)) + + /** + * Alias for [Builder.published]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun published(published: Long) = published(published as Long?) + + /** Alias for calling [Builder.published] with `published.orElse(null)`. */ + fun published(published: Optional) = published(published.getOrNull()) + + /** + * Sets [Builder.published] to an arbitrary JSON value. + * + * You should usually call [Builder.published] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun published(published: JsonField) = apply { this.published = published } + + fun version(version: String) = version(JsonField.of(version)) + + /** + * Sets [Builder.version] to an arbitrary JSON value. + * + * You should usually call [Builder.version] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun version(version: JsonField) = apply { this.version = version } + + 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 [JourneyVersionItem]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .created() + * .creator() + * .name() + * .published() + * .version() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyVersionItem = + JourneyVersionItem( + checkRequired("created", created), + checkRequired("creator", creator), + checkRequired("name", name), + checkRequired("published", published), + checkRequired("version", version), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyVersionItem = apply { + if (validated) { + return@apply + } + + created() + creator() + name() + published() + version() + 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 = + (if (created.asKnown().isPresent) 1 else 0) + + (if (creator.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (published.asKnown().isPresent) 1 else 0) + + (if (version.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyVersionItem && + created == other.created && + creator == other.creator && + name == other.name && + published == other.published && + version == other.version && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(created, creator, name, published, version, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyVersionItem{created=$created, creator=$creator, name=$name, published=$published, version=$version, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyVersionsListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyVersionsListResponse.kt new file mode 100644 index 00000000..7ecb16b8 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneyVersionsListResponse.kt @@ -0,0 +1,237 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.ExcludeMissing +import com.courier.core.JsonField +import com.courier.core.JsonMissing +import com.courier.core.JsonValue +import com.courier.core.checkKnown +import com.courier.core.checkRequired +import com.courier.core.toImmutable +import com.courier.errors.CourierInvalidDataException +import com.courier.models.Paging +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +/** Paged list of published journey versions, most recent first. */ +class JourneyVersionsListResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val paging: JsonField, + private val results: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("paging") @ExcludeMissing paging: JsonField = JsonMissing.of(), + @JsonProperty("results") + @ExcludeMissing + results: JsonField> = JsonMissing.of(), + ) : this(paging, results, 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). + */ + fun paging(): Paging = paging.getRequired("paging") + + /** + * @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 results(): List = results.getRequired("results") + + /** + * Returns the raw JSON value of [paging]. + * + * Unlike [paging], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("paging") @ExcludeMissing fun _paging(): JsonField = paging + + /** + * Returns the raw JSON value of [results]. + * + * Unlike [results], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("results") + @ExcludeMissing + fun _results(): JsonField> = results + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [JourneyVersionsListResponse]. + * + * The following fields are required: + * ```java + * .paging() + * .results() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [JourneyVersionsListResponse]. */ + class Builder internal constructor() { + + private var paging: JsonField? = null + private var results: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(journeyVersionsListResponse: JourneyVersionsListResponse) = apply { + paging = journeyVersionsListResponse.paging + results = journeyVersionsListResponse.results.map { it.toMutableList() } + additionalProperties = journeyVersionsListResponse.additionalProperties.toMutableMap() + } + + fun paging(paging: Paging) = paging(JsonField.of(paging)) + + /** + * Sets [Builder.paging] to an arbitrary JSON value. + * + * You should usually call [Builder.paging] with a well-typed [Paging] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun paging(paging: JsonField) = apply { this.paging = paging } + + fun results(results: List) = results(JsonField.of(results)) + + /** + * Sets [Builder.results] to an arbitrary JSON value. + * + * You should usually call [Builder.results] with a well-typed `List` + * value instead. This method is primarily for setting the field to an undocumented or not + * yet supported value. + */ + fun results(results: JsonField>) = apply { + this.results = results.map { it.toMutableList() } + } + + /** + * Adds a single [JourneyVersionItem] to [results]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addResult(result: JourneyVersionItem) = apply { + results = + (results ?: JsonField.of(mutableListOf())).also { + checkKnown("results", it).add(result) + } + } + + 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 [JourneyVersionsListResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .paging() + * .results() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): JourneyVersionsListResponse = + JourneyVersionsListResponse( + checkRequired("paging", paging), + checkRequired("results", results).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): JourneyVersionsListResponse = apply { + if (validated) { + return@apply + } + + paging().validate() + results().forEach { it.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 = + (paging.asKnown().getOrNull()?.validity() ?: 0) + + (results.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JourneyVersionsListResponse && + paging == other.paging && + results == other.results && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(paging, results, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "JourneyVersionsListResponse{paging=$paging, results=$results, additionalProperties=$additionalProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeRequest.kt index 91df020a..cba174a3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeRequest.kt @@ -200,6 +200,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): JourneysInvokeRequest = apply { if (validated) { return@apply @@ -294,6 +302,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -399,6 +416,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeResponse.kt index 06b82bad..2a899d0e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysInvokeResponse.kt @@ -130,6 +130,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): JourneysInvokeResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysListResponse.kt index 2ba010ef..aa4a9e6c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/JourneysListResponse.kt @@ -166,6 +166,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): JourneysListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateArchiveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateArchiveParams.kt new file mode 100644 index 00000000..0007b837 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateArchiveParams.kt @@ -0,0 +1,259 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Archive the journey-scoped notification template. Archived templates cannot be sent. */ +class TemplateArchiveParams +private constructor( + private val templateId: String, + private val notificationId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun templateId(): String = templateId + + fun notificationId(): Optional = Optional.ofNullable(notificationId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TemplateArchiveParams]. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplateArchiveParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var notificationId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(templateArchiveParams: TemplateArchiveParams) = apply { + templateId = templateArchiveParams.templateId + notificationId = templateArchiveParams.notificationId + additionalHeaders = templateArchiveParams.additionalHeaders.toBuilder() + additionalQueryParams = templateArchiveParams.additionalQueryParams.toBuilder() + additionalBodyProperties = templateArchiveParams.additionalBodyProperties.toMutableMap() + } + + fun templateId(templateId: String) = apply { this.templateId = templateId } + + fun notificationId(notificationId: String?) = apply { this.notificationId = notificationId } + + /** Alias for calling [Builder.notificationId] with `notificationId.orElse(null)`. */ + fun notificationId(notificationId: Optional) = + notificationId(notificationId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [TemplateArchiveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TemplateArchiveParams = + TemplateArchiveParams( + checkRequired("templateId", templateId), + notificationId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId + 1 -> notificationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplateArchiveParams && + templateId == other.templateId && + notificationId == other.notificationId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash( + templateId, + notificationId, + additionalHeaders, + additionalQueryParams, + additionalBodyProperties, + ) + + override fun toString() = + "TemplateArchiveParams{templateId=$templateId, notificationId=$notificationId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateCreateParams.kt new file mode 100644 index 00000000..ddd6f87d --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateCreateParams.kt @@ -0,0 +1,235 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.models.journeys.JourneyTemplateCreateRequest +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Create a notification template scoped to this journey. Defaults to `DRAFT` state; pass `state: + * "PUBLISHED"` to publish on create. + */ +class TemplateCreateParams +private constructor( + private val templateId: String?, + private val journeyTemplateCreateRequest: JourneyTemplateCreateRequest, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** Request body for creating a notification template scoped to a journey. */ + fun journeyTemplateCreateRequest(): JourneyTemplateCreateRequest = journeyTemplateCreateRequest + + fun _additionalBodyProperties(): Map = + journeyTemplateCreateRequest._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TemplateCreateParams]. + * + * The following fields are required: + * ```java + * .journeyTemplateCreateRequest() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplateCreateParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var journeyTemplateCreateRequest: JourneyTemplateCreateRequest? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(templateCreateParams: TemplateCreateParams) = apply { + templateId = templateCreateParams.templateId + journeyTemplateCreateRequest = templateCreateParams.journeyTemplateCreateRequest + additionalHeaders = templateCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = templateCreateParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + /** Request body for creating a notification template scoped to a journey. */ + fun journeyTemplateCreateRequest( + journeyTemplateCreateRequest: JourneyTemplateCreateRequest + ) = apply { this.journeyTemplateCreateRequest = journeyTemplateCreateRequest } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [TemplateCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .journeyTemplateCreateRequest() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TemplateCreateParams = + TemplateCreateParams( + templateId, + checkRequired("journeyTemplateCreateRequest", journeyTemplateCreateRequest), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JourneyTemplateCreateRequest = journeyTemplateCreateRequest + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplateCreateParams && + templateId == other.templateId && + journeyTemplateCreateRequest == other.journeyTemplateCreateRequest && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + templateId, + journeyTemplateCreateRequest, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "TemplateCreateParams{templateId=$templateId, journeyTemplateCreateRequest=$journeyTemplateCreateRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListParams.kt new file mode 100644 index 00000000..a6725636 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListParams.kt @@ -0,0 +1,239 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.Params +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * List notification templates scoped to this journey. Journey-scoped notification templates can + * only be referenced from `send` nodes within the same journey. + */ +class TemplateListParams +private constructor( + private val templateId: String?, + private val cursor: String?, + private val limit: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** Pagination cursor from a prior response. */ + fun cursor(): Optional = Optional.ofNullable(cursor) + + /** Page size. Minimum 1, maximum 100. */ + fun limit(): Optional = Optional.ofNullable(limit) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + @JvmStatic fun none(): TemplateListParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [TemplateListParams]. */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplateListParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var cursor: String? = null + private var limit: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(templateListParams: TemplateListParams) = apply { + templateId = templateListParams.templateId + cursor = templateListParams.cursor + limit = templateListParams.limit + additionalHeaders = templateListParams.additionalHeaders.toBuilder() + additionalQueryParams = templateListParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + /** Pagination cursor from a prior response. */ + fun cursor(cursor: String?) = apply { this.cursor = cursor } + + /** Alias for calling [Builder.cursor] with `cursor.orElse(null)`. */ + fun cursor(cursor: Optional) = cursor(cursor.getOrNull()) + + /** Page size. Minimum 1, maximum 100. */ + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * Alias for [Builder.limit]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** Alias for calling [Builder.limit] with `limit.orElse(null)`. */ + fun limit(limit: Optional) = limit(limit.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [TemplateListParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): TemplateListParams = + TemplateListParams( + templateId, + cursor, + limit, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + cursor?.let { put("cursor", it) } + limit?.let { put("limit", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplateListParams && + templateId == other.templateId && + cursor == other.cursor && + limit == other.limit && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(templateId, cursor, limit, additionalHeaders, additionalQueryParams) + + override fun toString() = + "TemplateListParams{templateId=$templateId, cursor=$cursor, limit=$limit, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParams.kt new file mode 100644 index 00000000..ac5fe853 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParams.kt @@ -0,0 +1,220 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * List published versions of the journey-scoped notification template, ordered most recent first. + */ +class TemplateListVersionsParams +private constructor( + private val templateId: String, + private val notificationId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): String = templateId + + fun notificationId(): Optional = Optional.ofNullable(notificationId) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TemplateListVersionsParams]. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplateListVersionsParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var notificationId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(templateListVersionsParams: TemplateListVersionsParams) = apply { + templateId = templateListVersionsParams.templateId + notificationId = templateListVersionsParams.notificationId + additionalHeaders = templateListVersionsParams.additionalHeaders.toBuilder() + additionalQueryParams = templateListVersionsParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String) = apply { this.templateId = templateId } + + fun notificationId(notificationId: String?) = apply { this.notificationId = notificationId } + + /** Alias for calling [Builder.notificationId] with `notificationId.orElse(null)`. */ + fun notificationId(notificationId: Optional) = + notificationId(notificationId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [TemplateListVersionsParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TemplateListVersionsParams = + TemplateListVersionsParams( + checkRequired("templateId", templateId), + notificationId, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId + 1 -> notificationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplateListVersionsParams && + templateId == other.templateId && + notificationId == other.notificationId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(templateId, notificationId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "TemplateListVersionsParams{templateId=$templateId, notificationId=$notificationId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplatePublishParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplatePublishParams.kt new file mode 100644 index 00000000..4f47593b --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplatePublishParams.kt @@ -0,0 +1,264 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.core.immutableEmptyMap +import com.courier.models.journeys.JourneyTemplatePublishRequest +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Publish the current draft of the journey-scoped notification template as a new version. + * Optionally roll back to a prior version by passing `{ "version": "vN" }`. + */ +class TemplatePublishParams +private constructor( + private val templateId: String, + private val notificationId: String?, + private val journeyTemplatePublishRequest: JourneyTemplatePublishRequest?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): String = templateId + + fun notificationId(): Optional = Optional.ofNullable(notificationId) + + /** + * Request body for publishing a journey-scoped notification template. Pass `version` to roll + * back to a prior version; omit to publish the current draft. + */ + fun journeyTemplatePublishRequest(): Optional = + Optional.ofNullable(journeyTemplatePublishRequest) + + fun _additionalBodyProperties(): Map = + journeyTemplatePublishRequest?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TemplatePublishParams]. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplatePublishParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var notificationId: String? = null + private var journeyTemplatePublishRequest: JourneyTemplatePublishRequest? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(templatePublishParams: TemplatePublishParams) = apply { + templateId = templatePublishParams.templateId + notificationId = templatePublishParams.notificationId + journeyTemplatePublishRequest = templatePublishParams.journeyTemplatePublishRequest + additionalHeaders = templatePublishParams.additionalHeaders.toBuilder() + additionalQueryParams = templatePublishParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String) = apply { this.templateId = templateId } + + fun notificationId(notificationId: String?) = apply { this.notificationId = notificationId } + + /** Alias for calling [Builder.notificationId] with `notificationId.orElse(null)`. */ + fun notificationId(notificationId: Optional) = + notificationId(notificationId.getOrNull()) + + /** + * Request body for publishing a journey-scoped notification template. Pass `version` to + * roll back to a prior version; omit to publish the current draft. + */ + fun journeyTemplatePublishRequest( + journeyTemplatePublishRequest: JourneyTemplatePublishRequest? + ) = apply { this.journeyTemplatePublishRequest = journeyTemplatePublishRequest } + + /** + * Alias for calling [Builder.journeyTemplatePublishRequest] with + * `journeyTemplatePublishRequest.orElse(null)`. + */ + fun journeyTemplatePublishRequest( + journeyTemplatePublishRequest: Optional + ) = journeyTemplatePublishRequest(journeyTemplatePublishRequest.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [TemplatePublishParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TemplatePublishParams = + TemplatePublishParams( + checkRequired("templateId", templateId), + notificationId, + journeyTemplatePublishRequest, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Optional = + Optional.ofNullable(journeyTemplatePublishRequest) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId + 1 -> notificationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplatePublishParams && + templateId == other.templateId && + notificationId == other.notificationId && + journeyTemplatePublishRequest == other.journeyTemplatePublishRequest && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + templateId, + notificationId, + journeyTemplatePublishRequest, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "TemplatePublishParams{templateId=$templateId, notificationId=$notificationId, journeyTemplatePublishRequest=$journeyTemplatePublishRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateReplaceParams.kt new file mode 100644 index 00000000..7408ee81 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateReplaceParams.kt @@ -0,0 +1,247 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.models.journeys.JourneyTemplateReplaceRequest +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** Replace the journey-scoped notification template draft. */ +class TemplateReplaceParams +private constructor( + private val templateId: String, + private val notificationId: String?, + private val journeyTemplateReplaceRequest: JourneyTemplateReplaceRequest, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): String = templateId + + fun notificationId(): Optional = Optional.ofNullable(notificationId) + + /** Request body for replacing a journey-scoped notification template draft. */ + fun journeyTemplateReplaceRequest(): JourneyTemplateReplaceRequest = + journeyTemplateReplaceRequest + + fun _additionalBodyProperties(): Map = + journeyTemplateReplaceRequest._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TemplateReplaceParams]. + * + * The following fields are required: + * ```java + * .templateId() + * .journeyTemplateReplaceRequest() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplateReplaceParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var notificationId: String? = null + private var journeyTemplateReplaceRequest: JourneyTemplateReplaceRequest? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(templateReplaceParams: TemplateReplaceParams) = apply { + templateId = templateReplaceParams.templateId + notificationId = templateReplaceParams.notificationId + journeyTemplateReplaceRequest = templateReplaceParams.journeyTemplateReplaceRequest + additionalHeaders = templateReplaceParams.additionalHeaders.toBuilder() + additionalQueryParams = templateReplaceParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String) = apply { this.templateId = templateId } + + fun notificationId(notificationId: String?) = apply { this.notificationId = notificationId } + + /** Alias for calling [Builder.notificationId] with `notificationId.orElse(null)`. */ + fun notificationId(notificationId: Optional) = + notificationId(notificationId.getOrNull()) + + /** Request body for replacing a journey-scoped notification template draft. */ + fun journeyTemplateReplaceRequest( + journeyTemplateReplaceRequest: JourneyTemplateReplaceRequest + ) = apply { this.journeyTemplateReplaceRequest = journeyTemplateReplaceRequest } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [TemplateReplaceParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .templateId() + * .journeyTemplateReplaceRequest() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TemplateReplaceParams = + TemplateReplaceParams( + checkRequired("templateId", templateId), + notificationId, + checkRequired("journeyTemplateReplaceRequest", journeyTemplateReplaceRequest), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): JourneyTemplateReplaceRequest = journeyTemplateReplaceRequest + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId + 1 -> notificationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplateReplaceParams && + templateId == other.templateId && + notificationId == other.notificationId && + journeyTemplateReplaceRequest == other.journeyTemplateReplaceRequest && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash( + templateId, + notificationId, + journeyTemplateReplaceRequest, + additionalHeaders, + additionalQueryParams, + ) + + override fun toString() = + "TemplateReplaceParams{templateId=$templateId, notificationId=$notificationId, journeyTemplateReplaceRequest=$journeyTemplateReplaceRequest, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParams.kt new file mode 100644 index 00000000..7292132b --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParams.kt @@ -0,0 +1,221 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Fetch a journey-scoped notification template by id. Pass `?version=draft` (default `published`) + * to retrieve the working draft, or `?version=vN` for a historical version. + */ +class TemplateRetrieveParams +private constructor( + private val templateId: String, + private val notificationId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun templateId(): String = templateId + + fun notificationId(): Optional = Optional.ofNullable(notificationId) + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TemplateRetrieveParams]. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplateRetrieveParams]. */ + class Builder internal constructor() { + + private var templateId: String? = null + private var notificationId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + @JvmSynthetic + internal fun from(templateRetrieveParams: TemplateRetrieveParams) = apply { + templateId = templateRetrieveParams.templateId + notificationId = templateRetrieveParams.notificationId + additionalHeaders = templateRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = templateRetrieveParams.additionalQueryParams.toBuilder() + } + + fun templateId(templateId: String) = apply { this.templateId = templateId } + + fun notificationId(notificationId: String?) = apply { this.notificationId = notificationId } + + /** Alias for calling [Builder.notificationId] with `notificationId.orElse(null)`. */ + fun notificationId(notificationId: Optional) = + notificationId(notificationId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [TemplateRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .templateId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TemplateRetrieveParams = + TemplateRetrieveParams( + checkRequired("templateId", templateId), + notificationId, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> templateId + 1 -> notificationId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplateRetrieveParams && + templateId == other.templateId && + notificationId == other.notificationId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(templateId, notificationId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "TemplateRetrieveParams{templateId=$templateId, notificationId=$notificationId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListResponse.kt index a035d0a3..64fbdee6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListListResponse.kt @@ -176,6 +176,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ListListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt index 6c53c5d6..775c573d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/ListUpdateParams.kt @@ -440,6 +440,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/PutSubscriptionsRecipient.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/PutSubscriptionsRecipient.kt index 18c3064e..f37ea0b5 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/PutSubscriptionsRecipient.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/PutSubscriptionsRecipient.kt @@ -173,6 +173,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PutSubscriptionsRecipient = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/SubscriptionList.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/SubscriptionList.kt index 732e44bf..ee4a5e27 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/SubscriptionList.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/SubscriptionList.kt @@ -221,6 +221,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SubscriptionList = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt index 33b7d0d9..18b58825 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionAddParams.kt @@ -409,6 +409,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListResponse.kt index 87e53fbf..c6030846 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionListResponse.kt @@ -176,6 +176,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SubscriptionListResponse = apply { if (validated) { return@apply @@ -395,6 +403,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Item = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeParams.kt index 14a6075c..387158a3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeParams.kt @@ -409,6 +409,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt index 315375e8..4a3dbd43 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/lists/subscriptions/SubscriptionSubscribeUserParams.kt @@ -388,6 +388,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentResponse.kt index fe13a85f..dc05356e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageContentResponse.kt @@ -148,6 +148,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageContentResponse = apply { if (validated) { return@apply @@ -360,6 +368,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Result = apply { if (validated) { return@apply @@ -705,6 +722,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Content = apply { if (validated) { return@apply @@ -901,6 +928,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Block = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt index 7c68c999..e5d409e0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageDetails.kt @@ -535,6 +535,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageDetails = apply { if (validated) { return@apply @@ -749,6 +757,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply @@ -917,6 +934,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Reason = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryResponse.kt index 3c51bca3..bf74e08b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageHistoryResponse.kt @@ -145,6 +145,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageHistoryResponse = apply { if (validated) { return@apply @@ -229,6 +237,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Result = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListResponse.kt index bf1b4505..7a10347e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageListResponse.kt @@ -186,6 +186,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveResponse.kt index c654f93f..c1771003 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/messages/MessageRetrieveResponse.kt @@ -609,6 +609,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MessageRetrieveResponse = apply { if (validated) { return@apply @@ -717,6 +725,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Provider = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/BaseCheck.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/BaseCheck.kt index 91d0fad5..bc61c325 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/BaseCheck.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/BaseCheck.kt @@ -189,6 +189,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BaseCheck = apply { if (validated) { return@apply @@ -312,6 +320,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply @@ -431,6 +448,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/Check.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/Check.kt index e63c15ec..a76235f9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/Check.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/Check.kt @@ -224,6 +224,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Check = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/ElementWithChecksums.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/ElementWithChecksums.kt index 5898769b..5575d9ef 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/ElementWithChecksums.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/ElementWithChecksums.kt @@ -277,6 +277,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ElementWithChecksums = apply { if (validated) { return@apply @@ -370,6 +378,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Locales = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentGetResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentGetResponse.kt index fab187a3..69d680a0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentGetResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentGetResponse.kt @@ -187,6 +187,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationContentGetResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentMutationResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentMutationResponse.kt index aeaa2ce9..f4c58e3a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentMutationResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentMutationResponse.kt @@ -259,6 +259,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationContentMutationResponse = apply { if (validated) { return@apply @@ -435,6 +443,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Element = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentPutRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentPutRequest.kt index 27ea8ed7..b69fb61c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentPutRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationContentPutRequest.kt @@ -181,6 +181,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationContentPutRequest = apply { if (validated) { return@apply @@ -432,6 +440,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Content = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationElementPutRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationElementPutRequest.kt index 3c6e0dc7..537cb0a0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationElementPutRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationElementPutRequest.kt @@ -329,6 +329,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationElementPutRequest = apply { if (validated) { return@apply @@ -425,6 +433,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationGetContent.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationGetContent.kt index d4365985..73bc8eb0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationGetContent.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationGetContent.kt @@ -226,6 +226,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationGetContent = apply { if (validated) { return@apply @@ -572,6 +580,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Block = apply { if (validated) { return@apply @@ -742,6 +759,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -805,6 +832,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, + * unless [visitor] overrides [Visitor.unknown]. To handle variants not known to this + * version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = content.accept(new Content.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -815,6 +872,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Content = apply { if (validated) { return@apply @@ -1118,6 +1185,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): NotificationContentHierarchy = apply { if (validated) { return@apply @@ -1230,6 +1307,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Locales = apply { if (validated) { return@apply @@ -1540,6 +1627,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Channel = apply { if (validated) { return@apply @@ -1709,6 +1805,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Content = apply { if (validated) { return@apply @@ -1818,6 +1924,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Locales = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt index d9701228..26bd1a27 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationListResponse.kt @@ -203,6 +203,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationListResponse = apply { if (validated) { return@apply @@ -259,6 +267,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = result.accept(new Result.Visitor>() { + * @Override + * public Optional visitNotification(Notification notification) { + * return Optional.of(notification.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { notification != null -> visitor.visitNotification(notification) @@ -269,6 +306,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Result = apply { if (validated) { return@apply @@ -842,6 +888,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Notification = apply { if (validated) { return@apply @@ -1019,6 +1075,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Tags = apply { if (validated) { return@apply @@ -1202,6 +1268,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Data = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationLocalePutRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationLocalePutRequest.kt index 3722a5b9..561486e8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationLocalePutRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationLocalePutRequest.kt @@ -191,6 +191,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationLocalePutRequest = apply { if (validated) { return@apply @@ -332,6 +340,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Element = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentResponse.kt index 30d6ca60..b1be8228 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationRetrieveContentResponse.kt @@ -52,6 +52,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = notificationRetrieveContentResponse.accept(new NotificationRetrieveContentResponse.Visitor>() { + * @Override + * public Optional visitContentGet(NotificationContentGetResponse contentGet) { + * return Optional.of(contentGet.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { contentGet != null -> visitor.visitContentGet(contentGet) @@ -61,6 +90,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationRetrieveContentResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt index cb960679..25fd0828 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateCreateRequest.kt @@ -184,6 +184,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplateCreateRequest = apply { if (validated) { return@apply @@ -303,6 +311,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): State = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt index dd90bfbe..959a47a8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePayload.kt @@ -337,6 +337,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplatePayload = apply { if (validated) { return@apply @@ -483,6 +491,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Brand = apply { if (validated) { return@apply @@ -643,6 +660,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Routing = apply { if (validated) { return@apply @@ -797,6 +823,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Subscription = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePublishRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePublishRequest.kt index 03ca91e3..e42dd12d 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePublishRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplatePublishRequest.kt @@ -122,6 +122,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplatePublishRequest = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt index d7cfc009..c5a66403 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateResponse.kt @@ -574,6 +574,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplateResponse = apply { if (validated) { return@apply @@ -710,6 +718,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): State = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateState.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateState.kt index f3872c33..22a40e80 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateState.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateState.kt @@ -99,6 +99,14 @@ private constructor(private val value: JsonField) : Enum { private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplateState = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateSummary.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateSummary.kt index 554b46f7..9df42446 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateSummary.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateSummary.kt @@ -363,6 +363,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplateSummary = apply { if (validated) { return@apply @@ -490,6 +498,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): State = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt index ef86b21d..269620dc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateUpdateRequest.kt @@ -187,6 +187,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplateUpdateRequest = apply { if (validated) { return@apply @@ -306,6 +314,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): State = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateVersionListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateVersionListResponse.kt index cab84f9d..42fa5dc4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateVersionListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/NotificationTemplateVersionListResponse.kt @@ -184,6 +184,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): NotificationTemplateVersionListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/VersionNode.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/VersionNode.kt index a03da177..f58d5f07 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/VersionNode.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/VersionNode.kt @@ -236,6 +236,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): VersionNode = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListResponse.kt index c9f27f61..13d8d1d6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckListResponse.kt @@ -146,6 +146,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CheckListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt index 567553e6..2554c0b8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateParams.kt @@ -408,6 +408,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateResponse.kt index d1cc9c15..4d96b37c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/notifications/checks/CheckUpdateResponse.kt @@ -146,6 +146,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CheckUpdateResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt index 351e16cb..ef16cfcb 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateParams.kt @@ -371,6 +371,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -473,6 +482,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateResponse.kt index a49aa8c1..e3cc882b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileCreateResponse.kt @@ -129,6 +129,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ProfileCreateResponse = apply { if (validated) { return@apply @@ -234,6 +242,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt index fbc25a67..5d6cf5d4 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceParams.kt @@ -373,6 +373,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -475,6 +484,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceResponse.kt index 8a71b713..12888c10 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileReplaceResponse.kt @@ -129,6 +129,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ProfileReplaceResponse = apply { if (validated) { return@apply @@ -234,6 +242,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveResponse.kt index 2d4f799f..68f74ad1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileRetrieveResponse.kt @@ -171,6 +171,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ProfileRetrieveResponse = apply { if (validated) { return@apply @@ -257,6 +265,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt index 4e294779..50244a27 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/ProfileUpdateParams.kt @@ -400,6 +400,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -628,6 +637,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Patch = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/SubscribeToListsRequestItem.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/SubscribeToListsRequestItem.kt index 01768375..cd158949 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/SubscribeToListsRequestItem.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/SubscribeToListsRequestItem.kt @@ -170,6 +170,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SubscribeToListsRequestItem = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteResponse.kt index d8c543d4..88bd8c66 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListDeleteResponse.kt @@ -126,6 +126,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ListDeleteResponse = apply { if (validated) { return@apply @@ -231,6 +239,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveResponse.kt index db0e2915..ca6dcaa0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListRetrieveResponse.kt @@ -181,6 +181,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ListRetrieveResponse = apply { if (validated) { return@apply @@ -468,6 +476,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Result = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt index 81d83ed7..cc61977f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeParams.kt @@ -401,6 +401,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeResponse.kt index 57c11119..153761d0 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/profiles/lists/ListSubscribeResponse.kt @@ -129,6 +129,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ListSubscribeResponse = apply { if (validated) { return@apply @@ -234,6 +242,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/Provider.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/Provider.kt index 0d2744d3..1198d293 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/Provider.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/Provider.kt @@ -339,6 +339,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Provider = apply { if (validated) { return@apply @@ -436,6 +444,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Settings = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt index 59b31b97..5ab1a1f3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderCreateParams.kt @@ -566,6 +566,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -685,6 +694,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Settings = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListResponse.kt index a7d7d9de..48612208 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderListResponse.kt @@ -179,6 +179,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ProviderListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt index 30103eaf..beb70565 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProviderUpdateParams.kt @@ -588,6 +588,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -706,6 +715,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Settings = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProvidersCatalogEntry.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProvidersCatalogEntry.kt index 56c42e21..e6deaabf 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/ProvidersCatalogEntry.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/ProvidersCatalogEntry.kt @@ -276,6 +276,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ProvidersCatalogEntry = apply { if (validated) { return@apply @@ -372,6 +380,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Settings = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListResponse.kt index e098c503..5c290f23 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/providers/catalog/CatalogListResponse.kt @@ -182,6 +182,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CatalogListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/AssociatedNotificationListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/AssociatedNotificationListResponse.kt index 878ebaaf..389574a3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/AssociatedNotificationListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/AssociatedNotificationListResponse.kt @@ -185,6 +185,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AssociatedNotificationListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateRequest.kt index 34f77e48..0fa28bdf 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyCreateRequest.kt @@ -333,6 +333,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): RoutingStrategyCreateRequest = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyGetResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyGetResponse.kt index e21e6de9..064a36d3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyGetResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyGetResponse.kt @@ -518,6 +518,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): RoutingStrategyGetResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListResponse.kt index 0f8601d7..a2dc5859 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyListResponse.kt @@ -181,6 +181,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): RoutingStrategyListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyReplaceRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyReplaceRequest.kt index a390c581..ea302965 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyReplaceRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategyReplaceRequest.kt @@ -337,6 +337,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): RoutingStrategyReplaceRequest = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategySummary.kt b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategySummary.kt index b5834bc8..136ea017 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategySummary.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/routingstrategies/RoutingStrategySummary.kt @@ -395,6 +395,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): RoutingStrategySummary = apply { if (validated) { return@apply 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 6ab54e4b..82b300cc 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 @@ -394,6 +394,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -1053,6 +1062,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Message = apply { if (validated) { return@apply @@ -1134,6 +1152,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, + * unless [visitor] overrides [Visitor.unknown]. To handle variants not known to this + * version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = content.accept(new Content.Visitor>() { + * @Override + * public Optional visitElementalContentSugar(ElementalContentSugar elementalContentSugar) { + * return Optional.of(elementalContentSugar.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { elementalContentSugar != null -> @@ -1144,6 +1192,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Content = apply { if (validated) { return@apply @@ -1361,6 +1419,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -1593,6 +1661,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Delay = apply { if (validated) { return@apply @@ -1819,6 +1897,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Expiry = apply { if (validated) { return@apply @@ -1872,6 +1960,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = expiresIn.accept(new ExpiresIn.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -1881,6 +1999,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): ExpiresIn = apply { if (validated) { return@apply @@ -2260,6 +2388,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -2445,6 +2583,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Preferences = apply { if (validated) { return@apply @@ -2674,6 +2822,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Routing = apply { if (validated) { return@apply @@ -2796,6 +2954,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Method = apply { if (validated) { return@apply @@ -3121,6 +3289,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Timeout = apply { if (validated) { return@apply @@ -3217,6 +3395,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Channel = apply { if (validated) { return@apply @@ -3365,6 +3553,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Criteria = apply { if (validated) { return@apply @@ -3464,6 +3662,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Provider = apply { if (validated) { return@apply @@ -3630,6 +3838,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, + * unless [visitor] overrides [Visitor.unknown]. To handle variants not known to this + * version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = to.accept(new To.Visitor>() { + * @Override + * public Optional visitUserRecipient(UserRecipient userRecipient) { + * return Optional.of(userRecipient.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { userRecipient != null -> visitor.visitUserRecipient(userRecipient) @@ -3648,6 +3886,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): To = apply { if (validated) { return@apply @@ -4055,6 +4303,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = recipient.accept(new Recipient.Visitor>() { + * @Override + * public Optional visitUser(UserRecipient user) { + * return Optional.of(user.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { user != null -> visitor.visitUser(user) @@ -4070,6 +4348,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): Recipient = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageResponse.kt index 9b8bfd2c..9e7abd0b 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/send/SendMessageResponse.kt @@ -138,6 +138,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SendMessageResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/BaseTemplateTenantAssociation.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/BaseTemplateTenantAssociation.kt index 3c52329c..abac0516 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/BaseTemplateTenantAssociation.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/BaseTemplateTenantAssociation.kt @@ -270,6 +270,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BaseTemplateTenantAssociation = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/DefaultPreferences.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/DefaultPreferences.kt index b69fe6da..3bad6af3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/DefaultPreferences.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/DefaultPreferences.kt @@ -134,6 +134,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): DefaultPreferences = apply { if (validated) { return@apply @@ -436,6 +444,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Item = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishRequest.kt index a6d1d9f3..71f2764a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishRequest.kt @@ -123,6 +123,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PostTenantTemplatePublishRequest = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishResponse.kt index b85d08cb..5e58deee 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PostTenantTemplatePublishResponse.kt @@ -205,6 +205,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PostTenantTemplatePublishResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateRequest.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateRequest.kt index c5b21b9e..445aaad2 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateRequest.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateRequest.kt @@ -174,6 +174,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PutTenantTemplateRequest = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateResponse.kt index dd002065..ee8659d8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/PutTenantTemplateResponse.kt @@ -209,6 +209,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PutTenantTemplateResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/SubscriptionTopicNew.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/SubscriptionTopicNew.kt index d737125f..9242a5c6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/SubscriptionTopicNew.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/SubscriptionTopicNew.kt @@ -245,6 +245,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SubscriptionTopicNew = apply { if (validated) { return@apply @@ -368,6 +376,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/Tenant.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/Tenant.kt index f70bb778..7373f6a8 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/Tenant.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/Tenant.kt @@ -381,6 +381,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tenant = apply { if (validated) { return@apply @@ -478,6 +486,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Properties = apply { if (validated) { return@apply @@ -578,6 +595,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): UserProfile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantAssociation.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantAssociation.kt index ca9df9ce..0adfdcfd 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantAssociation.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantAssociation.kt @@ -233,6 +233,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TenantAssociation = apply { if (validated) { return@apply @@ -324,6 +332,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply @@ -446,6 +463,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListResponse.kt index 2bad8398..f203aeea 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListResponse.kt @@ -319,6 +319,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TenantListResponse = apply { if (validated) { return@apply @@ -437,6 +445,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersResponse.kt index 2fe44ba1..ac256f19 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantListUsersResponse.kt @@ -319,6 +319,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TenantListUsersResponse = apply { if (validated) { return@apply @@ -437,6 +445,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantTemplateInput.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantTemplateInput.kt index 5bec0cc7..f6e4b870 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantTemplateInput.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantTemplateInput.kt @@ -244,6 +244,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TenantTemplateInput = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt index 949d70a9..b576d2b1 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/TenantUpdateParams.kt @@ -765,6 +765,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -894,6 +903,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Properties = apply { if (validated) { return@apply @@ -994,6 +1012,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): UserProfile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateDeleteParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateDeleteParams.kt new file mode 100644 index 00000000..dec1acab --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateDeleteParams.kt @@ -0,0 +1,265 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.tenants.templates + +import com.courier.core.JsonValue +import com.courier.core.Params +import com.courier.core.checkRequired +import com.courier.core.http.Headers +import com.courier.core.http.QueryParams +import com.courier.core.toImmutable +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull + +/** + * Deletes the tenant's notification template with the given `template_id`. + * + * Returns **204 No Content** with an empty body on success. + * + * Returns **404** if there is no template with this ID for the tenant, including a second `DELETE` + * after a successful removal. + */ +class TemplateDeleteParams +private constructor( + private val tenantId: String, + private val templateId: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun tenantId(): String = tenantId + + fun templateId(): Optional = Optional.ofNullable(templateId) + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [TemplateDeleteParams]. + * + * The following fields are required: + * ```java + * .tenantId() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [TemplateDeleteParams]. */ + class Builder internal constructor() { + + private var tenantId: String? = null + private var templateId: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(templateDeleteParams: TemplateDeleteParams) = apply { + tenantId = templateDeleteParams.tenantId + templateId = templateDeleteParams.templateId + additionalHeaders = templateDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = templateDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = templateDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun tenantId(tenantId: String) = apply { this.tenantId = tenantId } + + fun templateId(templateId: String?) = apply { this.templateId = templateId } + + /** Alias for calling [Builder.templateId] with `templateId.orElse(null)`. */ + fun templateId(templateId: Optional) = templateId(templateId.getOrNull()) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [TemplateDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .tenantId() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): TemplateDeleteParams = + TemplateDeleteParams( + checkRequired("tenantId", tenantId), + templateId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Optional> = + Optional.ofNullable(additionalBodyProperties.ifEmpty { null }) + + fun _pathParam(index: Int): String = + when (index) { + 0 -> tenantId + 1 -> templateId ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is TemplateDeleteParams && + tenantId == other.tenantId && + templateId == other.templateId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash( + tenantId, + templateId, + additionalHeaders, + additionalQueryParams, + additionalBodyProperties, + ) + + override fun toString() = + "TemplateDeleteParams{tenantId=$tenantId, templateId=$templateId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListResponse.kt index 7eece171..929ec2c7 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/tenants/templates/TemplateListResponse.kt @@ -319,6 +319,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TemplateListResponse = apply { if (validated) { return@apply @@ -437,6 +445,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -780,6 +797,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Item = apply { if (validated) { return@apply @@ -936,6 +962,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Data = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveResponse.kt index b3baecf5..9ddde72a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveResponse.kt @@ -182,6 +182,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PreferenceRetrieveResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicResponse.kt index f88029c3..364501f9 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceRetrieveTopicResponse.kt @@ -132,6 +132,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PreferenceRetrieveTopicResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt index d60b18ba..71cdde9e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicParams.kt @@ -405,6 +405,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -671,6 +680,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Topic = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicResponse.kt index 290e9d38..980d63ca 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/PreferenceUpdateOrCreateTopicResponse.kt @@ -131,6 +131,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PreferenceUpdateOrCreateTopicResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt index e7eed1dc..e7f6720f 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/preferences/TopicPreference.kt @@ -348,6 +348,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TopicPreference = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt index d6a2d8e1..d8f89fd3 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddMultipleParams.kt @@ -403,6 +403,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt index 14d96059..9b70b75a 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantAddSingleParams.kt @@ -373,6 +373,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -475,6 +484,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Profile = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListResponse.kt index d053d5ad..a2446b12 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tenants/TenantListResponse.kt @@ -320,6 +320,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TenantListResponse = apply { if (validated) { return@apply @@ -438,6 +446,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt index 3d80f81f..bec9977e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenAddSingleParams.kt @@ -664,6 +664,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -830,6 +839,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ProviderKey = apply { if (validated) { return@apply @@ -1160,6 +1178,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Device = apply { if (validated) { return@apply @@ -1249,6 +1276,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = expiryDate.accept(new ExpiryDate.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -1258,6 +1314,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ExpiryDate = apply { if (validated) { return@apply @@ -1602,6 +1667,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tracking = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListResponse.kt index 1b83d5d8..467b1c6e 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenListResponse.kt @@ -148,6 +148,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TokenListResponse = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveResponse.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveResponse.kt index fdb20a5f..6e28d9e6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveResponse.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenRetrieveResponse.kt @@ -409,6 +409,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): TokenRetrieveResponse = apply { if (validated) { return@apply @@ -546,6 +554,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt index 41bdfad6..b1425c5c 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/TokenUpdateParams.kt @@ -405,6 +405,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -634,6 +643,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Patch = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/UserToken.kt b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/UserToken.kt index 97262acf..5241cc08 100644 --- a/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/UserToken.kt +++ b/courier-java-core/src/main/kotlin/com/courier/models/users/tokens/UserToken.kt @@ -317,6 +317,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): UserToken = apply { if (validated) { return@apply @@ -453,6 +461,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ProviderKey = apply { if (validated) { return@apply @@ -783,6 +800,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Device = apply { if (validated) { return@apply @@ -872,6 +898,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.courier.core.JsonValue; + * import java.util.Optional; + * + * Optional result = expiryDate.accept(new ExpiryDate.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws CourierInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -881,6 +936,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ExpiryDate = apply { if (validated) { return@apply @@ -1225,6 +1289,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws CourierInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tracking = apply { if (validated) { return@apply diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt index e3faf14c..c7e0e767 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsync.kt @@ -4,11 +4,22 @@ package com.courier.services.async import com.courier.core.ClientOptions import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse import com.courier.core.http.HttpResponseFor +import com.courier.models.journeys.CreateJourneyRequest +import com.courier.models.journeys.JourneyArchiveParams +import com.courier.models.journeys.JourneyCreateParams import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams +import com.courier.models.journeys.JourneyListVersionsParams +import com.courier.models.journeys.JourneyPublishParams +import com.courier.models.journeys.JourneyReplaceParams +import com.courier.models.journeys.JourneyResponse +import com.courier.models.journeys.JourneyRetrieveParams +import com.courier.models.journeys.JourneyVersionsListResponse import com.courier.models.journeys.JourneysInvokeResponse import com.courier.models.journeys.JourneysListResponse +import com.courier.services.async.journeys.TemplateServiceAsync import java.util.concurrent.CompletableFuture import java.util.function.Consumer @@ -26,6 +37,76 @@ interface JourneyServiceAsync { */ fun withOptions(modifier: Consumer): JourneyServiceAsync + fun templates(): TemplateServiceAsync + + /** + * Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"` to publish on create. + * Send nodes are not allowed on `POST`. The standard flow is: create the journey shell here, + * add notification templates with `POST /journeys/{templateId}/templates`, then wire them into + * the journey with `PUT /journeys/{templateId}`. Call `POST /journeys/{templateId}/publish` to + * publish a draft after the fact. + */ + fun create(params: JourneyCreateParams): CompletableFuture = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see create */ + fun create( + createJourneyRequest: CreateJourneyRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + create( + JourneyCreateParams.builder().createJourneyRequest(createJourneyRequest).build(), + requestOptions, + ) + + /** @see create */ + fun create(createJourneyRequest: CreateJourneyRequest): CompletableFuture = + create(createJourneyRequest, RequestOptions.none()) + + /** + * Fetch a journey by id. Pass `?version=draft` (default `published`) to retrieve the working + * draft, or `?version=vN` to retrieve a historical version. + */ + fun retrieve(templateId: String): CompletableFuture = + retrieve(templateId, JourneyRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + ): CompletableFuture = retrieve(templateId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see retrieve */ + fun retrieve(params: JourneyRetrieveParams): CompletableFuture = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + retrieve(templateId, JourneyRetrieveParams.none(), requestOptions) + /** Get the list of journeys. */ fun list(): CompletableFuture = list(JourneyListParams.none()) @@ -44,7 +125,45 @@ interface JourneyServiceAsync { fun list(requestOptions: RequestOptions): CompletableFuture = list(JourneyListParams.none(), requestOptions) - /** Invoke a journey run from a journey template. */ + /** + * Archive a journey. Archived journeys cannot be invoked. Existing journey runs continue to + * completion. + */ + fun archive(templateId: String): CompletableFuture = + archive(templateId, JourneyArchiveParams.none()) + + /** @see archive */ + fun archive( + templateId: String, + params: JourneyArchiveParams = JourneyArchiveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + archive(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see archive */ + fun archive( + templateId: String, + params: JourneyArchiveParams = JourneyArchiveParams.none(), + ): CompletableFuture = archive(templateId, params, RequestOptions.none()) + + /** @see archive */ + fun archive( + params: JourneyArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see archive */ + fun archive(params: JourneyArchiveParams): CompletableFuture = + archive(params, RequestOptions.none()) + + /** @see archive */ + fun archive(templateId: String, requestOptions: RequestOptions): CompletableFuture = + archive(templateId, JourneyArchiveParams.none(), requestOptions) + + /** + * Invoke a journey by id or alias to start a new run. The response includes a `runId` + * identifying the run. + */ fun invoke( templateId: String, params: JourneyInvokeParams, @@ -68,6 +187,110 @@ interface JourneyServiceAsync { requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** List published versions of a journey, ordered most recent first. */ + fun listVersions(templateId: String): CompletableFuture = + listVersions(templateId, JourneyListVersionsParams.none()) + + /** @see listVersions */ + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + listVersions(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see listVersions */ + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + ): CompletableFuture = + listVersions(templateId, params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see listVersions */ + fun listVersions( + params: JourneyListVersionsParams + ): CompletableFuture = listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + listVersions(templateId, JourneyListVersionsParams.none(), requestOptions) + + /** + * Publish the current draft as a new version. Body is optional; pass `{ "version": "vN" }` to + * roll back to a prior version instead. Returns 404 if the journey has no draft to publish. + */ + fun publish(templateId: String): CompletableFuture = + publish(templateId, JourneyPublishParams.none()) + + /** @see publish */ + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + publish(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see publish */ + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + ): CompletableFuture = publish(templateId, params, RequestOptions.none()) + + /** @see publish */ + fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see publish */ + fun publish(params: JourneyPublishParams): CompletableFuture = + publish(params, RequestOptions.none()) + + /** @see publish */ + fun publish( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + publish(templateId, JourneyPublishParams.none(), requestOptions) + + /** + * Replace the journey draft. Updates the working draft only; call `POST + * /journeys/{templateId}/publish` to make it live, or pass `state: "PUBLISHED"` in this request + * to publish immediately. Send-node `template` ids must already exist and be scoped to this + * journey, and node ids must not be claimed by another journey. + */ + fun replace( + templateId: String, + params: JourneyReplaceParams, + ): CompletableFuture = replace(templateId, params, RequestOptions.none()) + + /** @see replace */ + fun replace( + templateId: String, + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + replace(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see replace */ + fun replace(params: JourneyReplaceParams): CompletableFuture = + replace(params, RequestOptions.none()) + + /** @see replace */ + fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + /** * A view of [JourneyServiceAsync] that provides access to raw HTTP responses for each method. */ @@ -82,6 +305,80 @@ interface JourneyServiceAsync { modifier: Consumer ): JourneyServiceAsync.WithRawResponse + fun templates(): TemplateServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /journeys`, but is otherwise the same as + * [JourneyServiceAsync.create]. + */ + fun create( + params: JourneyCreateParams + ): CompletableFuture> = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see create */ + fun create( + createJourneyRequest: CreateJourneyRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + create( + JourneyCreateParams.builder().createJourneyRequest(createJourneyRequest).build(), + requestOptions, + ) + + /** @see create */ + fun create( + createJourneyRequest: CreateJourneyRequest + ): CompletableFuture> = + create(createJourneyRequest, RequestOptions.none()) + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}`, but is otherwise the same + * as [JourneyServiceAsync.retrieve]. + */ + fun retrieve(templateId: String): CompletableFuture> = + retrieve(templateId, JourneyRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + ): CompletableFuture> = + retrieve(templateId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see retrieve */ + fun retrieve( + params: JourneyRetrieveParams + ): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + retrieve(templateId, JourneyRetrieveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `get /journeys`, but is otherwise the same as * [JourneyServiceAsync.list]. @@ -107,6 +404,44 @@ interface JourneyServiceAsync { ): CompletableFuture> = list(JourneyListParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `delete /journeys/{templateId}`, but is otherwise the + * same as [JourneyServiceAsync.archive]. + */ + fun archive(templateId: String): CompletableFuture = + archive(templateId, JourneyArchiveParams.none()) + + /** @see archive */ + fun archive( + templateId: String, + params: JourneyArchiveParams = JourneyArchiveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + archive(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see archive */ + fun archive( + templateId: String, + params: JourneyArchiveParams = JourneyArchiveParams.none(), + ): CompletableFuture = archive(templateId, params, RequestOptions.none()) + + /** @see archive */ + fun archive( + params: JourneyArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see archive */ + fun archive(params: JourneyArchiveParams): CompletableFuture = + archive(params, RequestOptions.none()) + + /** @see archive */ + fun archive( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + archive(templateId, JourneyArchiveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /journeys/{templateId}/invoke`, but is otherwise * the same as [JourneyServiceAsync.invoke]. @@ -136,5 +471,119 @@ interface JourneyServiceAsync { params: JourneyInvokeParams, requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}/versions`, but is otherwise + * the same as [JourneyServiceAsync.listVersions]. + */ + fun listVersions( + templateId: String + ): CompletableFuture> = + listVersions(templateId, JourneyListVersionsParams.none()) + + /** @see listVersions */ + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + listVersions(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see listVersions */ + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + ): CompletableFuture> = + listVersions(templateId, params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see listVersions */ + fun listVersions( + params: JourneyListVersionsParams + ): CompletableFuture> = + listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + listVersions(templateId, JourneyListVersionsParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /journeys/{templateId}/publish`, but is otherwise + * the same as [JourneyServiceAsync.publish]. + */ + fun publish(templateId: String): CompletableFuture> = + publish(templateId, JourneyPublishParams.none()) + + /** @see publish */ + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + publish(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see publish */ + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + ): CompletableFuture> = + publish(templateId, params, RequestOptions.none()) + + /** @see publish */ + fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see publish */ + fun publish( + params: JourneyPublishParams + ): CompletableFuture> = + publish(params, RequestOptions.none()) + + /** @see publish */ + fun publish( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + publish(templateId, JourneyPublishParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /journeys/{templateId}`, but is otherwise the same + * as [JourneyServiceAsync.replace]. + */ + fun replace( + templateId: String, + params: JourneyReplaceParams, + ): CompletableFuture> = + replace(templateId, params, RequestOptions.none()) + + /** @see replace */ + fun replace( + templateId: String, + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + replace(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see replace */ + fun replace( + params: JourneyReplaceParams + ): CompletableFuture> = + replace(params, RequestOptions.none()) + + /** @see replace */ + fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt index 3aee99df..85afc2ec 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/JourneyServiceAsyncImpl.kt @@ -5,6 +5,7 @@ package com.courier.services.async import com.courier.core.ClientOptions import com.courier.core.RequestOptions import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler import com.courier.core.handlers.errorBodyHandler import com.courier.core.handlers.errorHandler import com.courier.core.handlers.jsonHandler @@ -16,10 +17,20 @@ import com.courier.core.http.HttpResponseFor import com.courier.core.http.json import com.courier.core.http.parseable import com.courier.core.prepareAsync +import com.courier.models.journeys.JourneyArchiveParams +import com.courier.models.journeys.JourneyCreateParams import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams +import com.courier.models.journeys.JourneyListVersionsParams +import com.courier.models.journeys.JourneyPublishParams +import com.courier.models.journeys.JourneyReplaceParams +import com.courier.models.journeys.JourneyResponse +import com.courier.models.journeys.JourneyRetrieveParams +import com.courier.models.journeys.JourneyVersionsListResponse import com.courier.models.journeys.JourneysInvokeResponse import com.courier.models.journeys.JourneysListResponse +import com.courier.services.async.journeys.TemplateServiceAsync +import com.courier.services.async.journeys.TemplateServiceAsyncImpl import java.util.concurrent.CompletableFuture import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull @@ -31,11 +42,29 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl WithRawResponseImpl(clientOptions) } + private val templates: TemplateServiceAsync by lazy { TemplateServiceAsyncImpl(clientOptions) } + override fun withRawResponse(): JourneyServiceAsync.WithRawResponse = withRawResponse override fun withOptions(modifier: Consumer): JourneyServiceAsync = JourneyServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun templates(): TemplateServiceAsync = templates + + override fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /journeys + withRawResponse().create(params, requestOptions).thenApply { it.parse() } + + override fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /journeys/{templateId} + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + override fun list( params: JourneyListParams, requestOptions: RequestOptions, @@ -43,6 +72,13 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl // get /journeys withRawResponse().list(params, requestOptions).thenApply { it.parse() } + override fun archive( + params: JourneyArchiveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // delete /journeys/{templateId} + withRawResponse().archive(params, requestOptions).thenAccept {} + override fun invoke( params: JourneyInvokeParams, requestOptions: RequestOptions, @@ -50,12 +86,37 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl // post /journeys/{templateId}/invoke withRawResponse().invoke(params, requestOptions).thenApply { it.parse() } + override fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /journeys/{templateId}/versions + withRawResponse().listVersions(params, requestOptions).thenApply { it.parse() } + + override fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /journeys/{templateId}/publish + withRawResponse().publish(params, requestOptions).thenApply { it.parse() } + + override fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // put /journeys/{templateId} + withRawResponse().replace(params, requestOptions).thenApply { it.parse() } + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : JourneyServiceAsync.WithRawResponse { private val errorHandler: Handler = errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + private val templates: TemplateServiceAsync.WithRawResponse by lazy { + TemplateServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + override fun withOptions( modifier: Consumer ): JourneyServiceAsync.WithRawResponse = @@ -63,6 +124,72 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl clientOptions.toBuilder().apply(modifier::accept).build() ) + override fun templates(): TemplateServiceAsync.WithRawResponse = templates + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + private val listHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -93,6 +220,33 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl } } + private val archiveHandler: Handler = emptyHandler() + + override fun archive( + params: JourneyArchiveParams, + requestOptions: RequestOptions, + ): CompletableFuture { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0)) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response.use { archiveHandler.handle(it) } + } + } + } + private val invokeHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -126,5 +280,106 @@ class JourneyServiceAsyncImpl internal constructor(private val clientOptions: Cl } } } + + private val listVersionsHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "versions") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { listVersionsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val publishHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "publish") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { publishHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val replaceHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0)) + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { replaceHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsync.kt new file mode 100644 index 00000000..e3386773 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsync.kt @@ -0,0 +1,467 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.journeys + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponseFor +import com.courier.models.journeys.JourneyTemplateGetResponse +import com.courier.models.journeys.JourneyTemplateListResponse +import com.courier.models.journeys.templates.TemplateArchiveParams +import com.courier.models.journeys.templates.TemplateCreateParams +import com.courier.models.journeys.templates.TemplateListParams +import com.courier.models.journeys.templates.TemplateListVersionsParams +import com.courier.models.journeys.templates.TemplatePublishParams +import com.courier.models.journeys.templates.TemplateReplaceParams +import com.courier.models.journeys.templates.TemplateRetrieveParams +import com.courier.models.notifications.NotificationTemplateVersionListResponse +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer + +interface TemplateServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): TemplateServiceAsync + + /** + * Create a notification template scoped to this journey. Defaults to `DRAFT` state; pass + * `state: "PUBLISHED"` to publish on create. + */ + fun create( + templateId: String, + params: TemplateCreateParams, + ): CompletableFuture = + create(templateId, params, RequestOptions.none()) + + /** @see create */ + fun create( + templateId: String, + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + create(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see create */ + fun create(params: TemplateCreateParams): CompletableFuture = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * Fetch a journey-scoped notification template by id. Pass `?version=draft` (default + * `published`) to retrieve the working draft, or `?version=vN` for a historical version. + */ + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + ): CompletableFuture = + retrieve(notificationId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + retrieve(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve(params: TemplateRetrieveParams): CompletableFuture = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * List notification templates scoped to this journey. Journey-scoped notification templates can + * only be referenced from `send` nodes within the same journey. + */ + fun list(templateId: String): CompletableFuture = + list(templateId, TemplateListParams.none()) + + /** @see list */ + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + list(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see list */ + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + ): CompletableFuture = + list(templateId, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: TemplateListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** @see list */ + fun list(params: TemplateListParams): CompletableFuture = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture = + list(templateId, TemplateListParams.none(), requestOptions) + + /** Archive the journey-scoped notification template. Archived templates cannot be sent. */ + fun archive(notificationId: String, params: TemplateArchiveParams): CompletableFuture = + archive(notificationId, params, RequestOptions.none()) + + /** @see archive */ + fun archive( + notificationId: String, + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + archive(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see archive */ + fun archive(params: TemplateArchiveParams): CompletableFuture = + archive(params, RequestOptions.none()) + + /** @see archive */ + fun archive( + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * List published versions of the journey-scoped notification template, ordered most recent + * first. + */ + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + ): CompletableFuture = + listVersions(notificationId, params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + listVersions(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see listVersions */ + fun listVersions( + params: TemplateListVersionsParams + ): CompletableFuture = + listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * Publish the current draft of the journey-scoped notification template as a new version. + * Optionally roll back to a prior version by passing `{ "version": "vN" }`. + */ + fun publish(notificationId: String, params: TemplatePublishParams): CompletableFuture = + publish(notificationId, params, RequestOptions.none()) + + /** @see publish */ + fun publish( + notificationId: String, + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + publish(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see publish */ + fun publish(params: TemplatePublishParams): CompletableFuture = + publish(params, RequestOptions.none()) + + /** @see publish */ + fun publish( + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** Replace the journey-scoped notification template draft. */ + fun replace( + notificationId: String, + params: TemplateReplaceParams, + ): CompletableFuture = + replace(notificationId, params, RequestOptions.none()) + + /** @see replace */ + fun replace( + notificationId: String, + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + replace(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see replace */ + fun replace(params: TemplateReplaceParams): CompletableFuture = + replace(params, RequestOptions.none()) + + /** @see replace */ + fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * A view of [TemplateServiceAsync] that provides access to raw HTTP responses for each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: Consumer + ): TemplateServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /journeys/{templateId}/templates`, but is otherwise + * the same as [TemplateServiceAsync.create]. + */ + fun create( + templateId: String, + params: TemplateCreateParams, + ): CompletableFuture> = + create(templateId, params, RequestOptions.none()) + + /** @see create */ + fun create( + templateId: String, + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + create(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see create */ + fun create( + params: TemplateCreateParams + ): CompletableFuture> = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}/templates/{notificationId}`, + * but is otherwise the same as [TemplateServiceAsync.retrieve]. + */ + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + ): CompletableFuture> = + retrieve(notificationId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + retrieve(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: TemplateRetrieveParams + ): CompletableFuture> = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}/templates`, but is otherwise + * the same as [TemplateServiceAsync.list]. + */ + fun list( + templateId: String + ): CompletableFuture> = + list(templateId, TemplateListParams.none()) + + /** @see list */ + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + list(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see list */ + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + ): CompletableFuture> = + list(templateId, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: TemplateListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see list */ + fun list( + params: TemplateListParams + ): CompletableFuture> = + list(params, RequestOptions.none()) + + /** @see list */ + fun list( + templateId: String, + requestOptions: RequestOptions, + ): CompletableFuture> = + list(templateId, TemplateListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete + * /journeys/{templateId}/templates/{notificationId}`, but is otherwise the same as + * [TemplateServiceAsync.archive]. + */ + fun archive( + notificationId: String, + params: TemplateArchiveParams, + ): CompletableFuture = archive(notificationId, params, RequestOptions.none()) + + /** @see archive */ + fun archive( + notificationId: String, + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + archive(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see archive */ + fun archive(params: TemplateArchiveParams): CompletableFuture = + archive(params, RequestOptions.none()) + + /** @see archive */ + fun archive( + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * Returns a raw HTTP response for `get + * /journeys/{templateId}/templates/{notificationId}/versions`, but is otherwise the same as + * [TemplateServiceAsync.listVersions]. + */ + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + ): CompletableFuture> = + listVersions(notificationId, params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + listVersions(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see listVersions */ + fun listVersions( + params: TemplateListVersionsParams + ): CompletableFuture> = + listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** + * Returns a raw HTTP response for `post + * /journeys/{templateId}/templates/{notificationId}/publish`, but is otherwise the same as + * [TemplateServiceAsync.publish]. + */ + fun publish( + notificationId: String, + params: TemplatePublishParams, + ): CompletableFuture = publish(notificationId, params, RequestOptions.none()) + + /** @see publish */ + fun publish( + notificationId: String, + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + publish(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see publish */ + fun publish(params: TemplatePublishParams): CompletableFuture = + publish(params, RequestOptions.none()) + + /** @see publish */ + fun publish( + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + + /** + * Returns a raw HTTP response for `put /journeys/{templateId}/templates/{notificationId}`, + * but is otherwise the same as [TemplateServiceAsync.replace]. + */ + fun replace( + notificationId: String, + params: TemplateReplaceParams, + ): CompletableFuture> = + replace(notificationId, params, RequestOptions.none()) + + /** @see replace */ + fun replace( + notificationId: String, + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + replace(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see replace */ + fun replace( + params: TemplateReplaceParams + ): CompletableFuture> = + replace(params, RequestOptions.none()) + + /** @see replace */ + fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncImpl.kt new file mode 100644 index 00000000..a60ede8f --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncImpl.kt @@ -0,0 +1,356 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.journeys + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler +import com.courier.core.handlers.errorBodyHandler +import com.courier.core.handlers.errorHandler +import com.courier.core.handlers.jsonHandler +import com.courier.core.http.HttpMethod +import com.courier.core.http.HttpRequest +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponse.Handler +import com.courier.core.http.HttpResponseFor +import com.courier.core.http.json +import com.courier.core.http.parseable +import com.courier.core.prepareAsync +import com.courier.models.journeys.JourneyTemplateGetResponse +import com.courier.models.journeys.JourneyTemplateListResponse +import com.courier.models.journeys.templates.TemplateArchiveParams +import com.courier.models.journeys.templates.TemplateCreateParams +import com.courier.models.journeys.templates.TemplateListParams +import com.courier.models.journeys.templates.TemplateListVersionsParams +import com.courier.models.journeys.templates.TemplatePublishParams +import com.courier.models.journeys.templates.TemplateReplaceParams +import com.courier.models.journeys.templates.TemplateRetrieveParams +import com.courier.models.notifications.NotificationTemplateVersionListResponse +import java.util.concurrent.CompletableFuture +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class TemplateServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + TemplateServiceAsync { + + private val withRawResponse: TemplateServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): TemplateServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): TemplateServiceAsync = + TemplateServiceAsyncImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /journeys/{templateId}/templates + withRawResponse().create(params, requestOptions).thenApply { it.parse() } + + override fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /journeys/{templateId}/templates/{notificationId} + withRawResponse().retrieve(params, requestOptions).thenApply { it.parse() } + + override fun list( + params: TemplateListParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /journeys/{templateId}/templates + withRawResponse().list(params, requestOptions).thenApply { it.parse() } + + override fun archive( + params: TemplateArchiveParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // delete /journeys/{templateId}/templates/{notificationId} + withRawResponse().archive(params, requestOptions).thenAccept {} + + override fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // get /journeys/{templateId}/templates/{notificationId}/versions + withRawResponse().listVersions(params, requestOptions).thenApply { it.parse() } + + override fun publish( + params: TemplatePublishParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // post /journeys/{templateId}/templates/{notificationId}/publish + withRawResponse().publish(params, requestOptions).thenAccept {} + + override fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // put /journeys/{templateId}/templates/{notificationId} + withRawResponse().replace(params, requestOptions).thenApply { it.parse() } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + TemplateServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): TemplateServiceAsync.WithRawResponse = + TemplateServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "templates") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: TemplateListParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "templates") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val archiveHandler: Handler = emptyHandler() + + override fun archive( + params: TemplateArchiveParams, + requestOptions: RequestOptions, + ): CompletableFuture { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response.use { archiveHandler.handle(it) } + } + } + } + + private val listVersionsHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + "versions", + ) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { listVersionsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + + private val publishHandler: Handler = emptyHandler() + + override fun publish( + params: TemplatePublishParams, + requestOptions: RequestOptions, + ): CompletableFuture { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + "publish", + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response.use { publishHandler.handle(it) } + } + } + } + + private val replaceHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions, + ): CompletableFuture> { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response + .use { replaceHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt index bb42e1ff..57af2f50 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsync.kt @@ -4,10 +4,12 @@ package com.courier.services.async.tenants import com.courier.core.ClientOptions import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse import com.courier.core.http.HttpResponseFor import com.courier.models.tenants.BaseTemplateTenantAssociation import com.courier.models.tenants.PostTenantTemplatePublishResponse import com.courier.models.tenants.PutTenantTemplateResponse +import com.courier.models.tenants.templates.TemplateDeleteParams import com.courier.models.tenants.templates.TemplateListParams import com.courier.models.tenants.templates.TemplateListResponse import com.courier.models.tenants.templates.TemplatePublishParams @@ -93,6 +95,35 @@ interface TemplateServiceAsync { ): CompletableFuture = list(tenantId, TemplateListParams.none(), requestOptions) + /** + * Deletes the tenant's notification template with the given `template_id`. + * + * Returns **204 No Content** with an empty body on success. + * + * Returns **404** if there is no template with this ID for the tenant, including a second + * `DELETE` after a successful removal. + */ + fun delete(templateId: String, params: TemplateDeleteParams): CompletableFuture = + delete(templateId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + templateId: String, + params: TemplateDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + delete(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see delete */ + fun delete(params: TemplateDeleteParams): CompletableFuture = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: TemplateDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + /** * Publishes a specific version of a notification template for a tenant. * @@ -243,6 +274,33 @@ interface TemplateServiceAsync { ): CompletableFuture> = list(tenantId, TemplateListParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `delete /tenants/{tenant_id}/templates/{template_id}`, + * but is otherwise the same as [TemplateServiceAsync.delete]. + */ + fun delete( + templateId: String, + params: TemplateDeleteParams, + ): CompletableFuture = delete(templateId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + templateId: String, + params: TemplateDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + delete(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see delete */ + fun delete(params: TemplateDeleteParams): CompletableFuture = + delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete( + params: TemplateDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture + /** * Returns a raw HTTP response for `post * /tenants/{tenant_id}/templates/{template_id}/publish`, but is otherwise the same as diff --git a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt index 9b367d87..70affccc 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncImpl.kt @@ -5,6 +5,7 @@ package com.courier.services.async.tenants import com.courier.core.ClientOptions import com.courier.core.RequestOptions import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler import com.courier.core.handlers.errorBodyHandler import com.courier.core.handlers.errorHandler import com.courier.core.handlers.jsonHandler @@ -19,6 +20,7 @@ import com.courier.core.prepareAsync import com.courier.models.tenants.BaseTemplateTenantAssociation import com.courier.models.tenants.PostTenantTemplatePublishResponse import com.courier.models.tenants.PutTenantTemplateResponse +import com.courier.models.tenants.templates.TemplateDeleteParams import com.courier.models.tenants.templates.TemplateListParams import com.courier.models.tenants.templates.TemplateListResponse import com.courier.models.tenants.templates.TemplatePublishParams @@ -60,6 +62,13 @@ class TemplateServiceAsyncImpl internal constructor(private val clientOptions: C // get /tenants/{tenant_id}/templates withRawResponse().list(params, requestOptions).thenApply { it.parse() } + override fun delete( + params: TemplateDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture = + // delete /tenants/{tenant_id}/templates/{template_id} + withRawResponse().delete(params, requestOptions).thenAccept {} + override fun publish( params: TemplatePublishParams, requestOptions: RequestOptions, @@ -164,6 +173,38 @@ class TemplateServiceAsyncImpl internal constructor(private val clientOptions: C } } + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: TemplateDeleteParams, + requestOptions: RequestOptions, + ): CompletableFuture { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "tenants", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + return request + .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } + .thenApply { response -> + errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + } + private val publishHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt index 9f511df8..9d7484d6 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyService.kt @@ -4,11 +4,22 @@ package com.courier.services.blocking import com.courier.core.ClientOptions import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse import com.courier.core.http.HttpResponseFor +import com.courier.models.journeys.CreateJourneyRequest +import com.courier.models.journeys.JourneyArchiveParams +import com.courier.models.journeys.JourneyCreateParams import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams +import com.courier.models.journeys.JourneyListVersionsParams +import com.courier.models.journeys.JourneyPublishParams +import com.courier.models.journeys.JourneyReplaceParams +import com.courier.models.journeys.JourneyResponse +import com.courier.models.journeys.JourneyRetrieveParams +import com.courier.models.journeys.JourneyVersionsListResponse import com.courier.models.journeys.JourneysInvokeResponse import com.courier.models.journeys.JourneysListResponse +import com.courier.services.blocking.journeys.TemplateService import com.google.errorprone.annotations.MustBeClosed import java.util.function.Consumer @@ -26,6 +37,71 @@ interface JourneyService { */ fun withOptions(modifier: Consumer): JourneyService + fun templates(): TemplateService + + /** + * Create a journey. Defaults to `DRAFT` state; pass `state: "PUBLISHED"` to publish on create. + * Send nodes are not allowed on `POST`. The standard flow is: create the journey shell here, + * add notification templates with `POST /journeys/{templateId}/templates`, then wire them into + * the journey with `PUT /journeys/{templateId}`. Call `POST /journeys/{templateId}/publish` to + * publish a draft after the fact. + */ + fun create(params: JourneyCreateParams): JourneyResponse = create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse + + /** @see create */ + fun create( + createJourneyRequest: CreateJourneyRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse = + create( + JourneyCreateParams.builder().createJourneyRequest(createJourneyRequest).build(), + requestOptions, + ) + + /** @see create */ + fun create(createJourneyRequest: CreateJourneyRequest): JourneyResponse = + create(createJourneyRequest, RequestOptions.none()) + + /** + * Fetch a journey by id. Pass `?version=draft` (default `published`) to retrieve the working + * draft, or `?version=vN` to retrieve a historical version. + */ + fun retrieve(templateId: String): JourneyResponse = + retrieve(templateId, JourneyRetrieveParams.none()) + + /** @see retrieve */ + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse = retrieve(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + ): JourneyResponse = retrieve(templateId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse + + /** @see retrieve */ + fun retrieve(params: JourneyRetrieveParams): JourneyResponse = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve(templateId: String, requestOptions: RequestOptions): JourneyResponse = + retrieve(templateId, JourneyRetrieveParams.none(), requestOptions) + /** Get the list of journeys. */ fun list(): JourneysListResponse = list(JourneyListParams.none()) @@ -43,7 +119,40 @@ interface JourneyService { fun list(requestOptions: RequestOptions): JourneysListResponse = list(JourneyListParams.none(), requestOptions) - /** Invoke a journey run from a journey template. */ + /** + * Archive a journey. Archived journeys cannot be invoked. Existing journey runs continue to + * completion. + */ + fun archive(templateId: String) = archive(templateId, JourneyArchiveParams.none()) + + /** @see archive */ + fun archive( + templateId: String, + params: JourneyArchiveParams = JourneyArchiveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = archive(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see archive */ + fun archive(templateId: String, params: JourneyArchiveParams = JourneyArchiveParams.none()) = + archive(templateId, params, RequestOptions.none()) + + /** @see archive */ + fun archive( + params: JourneyArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see archive */ + fun archive(params: JourneyArchiveParams) = archive(params, RequestOptions.none()) + + /** @see archive */ + fun archive(templateId: String, requestOptions: RequestOptions) = + archive(templateId, JourneyArchiveParams.none(), requestOptions) + + /** + * Invoke a journey by id or alias to start a new run. The response includes a `runId` + * identifying the run. + */ fun invoke(templateId: String, params: JourneyInvokeParams): JourneysInvokeResponse = invoke(templateId, params, RequestOptions.none()) @@ -65,6 +174,101 @@ interface JourneyService { requestOptions: RequestOptions = RequestOptions.none(), ): JourneysInvokeResponse + /** List published versions of a journey, ordered most recent first. */ + fun listVersions(templateId: String): JourneyVersionsListResponse = + listVersions(templateId, JourneyListVersionsParams.none()) + + /** @see listVersions */ + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyVersionsListResponse = + listVersions(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see listVersions */ + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + ): JourneyVersionsListResponse = listVersions(templateId, params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyVersionsListResponse + + /** @see listVersions */ + fun listVersions(params: JourneyListVersionsParams): JourneyVersionsListResponse = + listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + templateId: String, + requestOptions: RequestOptions, + ): JourneyVersionsListResponse = + listVersions(templateId, JourneyListVersionsParams.none(), requestOptions) + + /** + * Publish the current draft as a new version. Body is optional; pass `{ "version": "vN" }` to + * roll back to a prior version instead. Returns 404 if the journey has no draft to publish. + */ + fun publish(templateId: String): JourneyResponse = + publish(templateId, JourneyPublishParams.none()) + + /** @see publish */ + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse = publish(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see publish */ + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + ): JourneyResponse = publish(templateId, params, RequestOptions.none()) + + /** @see publish */ + fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse + + /** @see publish */ + fun publish(params: JourneyPublishParams): JourneyResponse = + publish(params, RequestOptions.none()) + + /** @see publish */ + fun publish(templateId: String, requestOptions: RequestOptions): JourneyResponse = + publish(templateId, JourneyPublishParams.none(), requestOptions) + + /** + * Replace the journey draft. Updates the working draft only; call `POST + * /journeys/{templateId}/publish` to make it live, or pass `state: "PUBLISHED"` in this request + * to publish immediately. Send-node `template` ids must already exist and be scoped to this + * journey, and node ids must not be claimed by another journey. + */ + fun replace(templateId: String, params: JourneyReplaceParams): JourneyResponse = + replace(templateId, params, RequestOptions.none()) + + /** @see replace */ + fun replace( + templateId: String, + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse = replace(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see replace */ + fun replace(params: JourneyReplaceParams): JourneyResponse = + replace(params, RequestOptions.none()) + + /** @see replace */ + fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyResponse + /** A view of [JourneyService] that provides access to raw HTTP responses for each method. */ interface WithRawResponse { @@ -75,6 +279,83 @@ interface JourneyService { */ fun withOptions(modifier: Consumer): JourneyService.WithRawResponse + fun templates(): TemplateService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /journeys`, but is otherwise the same as + * [JourneyService.create]. + */ + @MustBeClosed + fun create(params: JourneyCreateParams): HttpResponseFor = + create(params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + createJourneyRequest: CreateJourneyRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create( + JourneyCreateParams.builder().createJourneyRequest(createJourneyRequest).build(), + requestOptions, + ) + + /** @see create */ + @MustBeClosed + fun create(createJourneyRequest: CreateJourneyRequest): HttpResponseFor = + create(createJourneyRequest, RequestOptions.none()) + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}`, but is otherwise the same + * as [JourneyService.retrieve]. + */ + @MustBeClosed + fun retrieve(templateId: String): HttpResponseFor = + retrieve(templateId, JourneyRetrieveParams.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + templateId: String, + params: JourneyRetrieveParams = JourneyRetrieveParams.none(), + ): HttpResponseFor = retrieve(templateId, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(params: JourneyRetrieveParams): HttpResponseFor = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + templateId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + retrieve(templateId, JourneyRetrieveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `get /journeys`, but is otherwise the same as * [JourneyService.list]. @@ -100,6 +381,46 @@ interface JourneyService { fun list(requestOptions: RequestOptions): HttpResponseFor = list(JourneyListParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `delete /journeys/{templateId}`, but is otherwise the + * same as [JourneyService.archive]. + */ + @MustBeClosed + fun archive(templateId: String): HttpResponse = + archive(templateId, JourneyArchiveParams.none()) + + /** @see archive */ + @MustBeClosed + fun archive( + templateId: String, + params: JourneyArchiveParams = JourneyArchiveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = archive(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see archive */ + @MustBeClosed + fun archive( + templateId: String, + params: JourneyArchiveParams = JourneyArchiveParams.none(), + ): HttpResponse = archive(templateId, params, RequestOptions.none()) + + /** @see archive */ + @MustBeClosed + fun archive( + params: JourneyArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see archive */ + @MustBeClosed + fun archive(params: JourneyArchiveParams): HttpResponse = + archive(params, RequestOptions.none()) + + /** @see archive */ + @MustBeClosed + fun archive(templateId: String, requestOptions: RequestOptions): HttpResponse = + archive(templateId, JourneyArchiveParams.none(), requestOptions) + /** * Returns a raw HTTP response for `post /journeys/{templateId}/invoke`, but is otherwise * the same as [JourneyService.invoke]. @@ -131,5 +452,127 @@ interface JourneyService { params: JourneyInvokeParams, requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}/versions`, but is otherwise + * the same as [JourneyService.listVersions]. + */ + @MustBeClosed + fun listVersions(templateId: String): HttpResponseFor = + listVersions(templateId, JourneyListVersionsParams.none()) + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + listVersions(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + templateId: String, + params: JourneyListVersionsParams = JourneyListVersionsParams.none(), + ): HttpResponseFor = + listVersions(templateId, params, RequestOptions.none()) + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + params: JourneyListVersionsParams + ): HttpResponseFor = + listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + templateId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + listVersions(templateId, JourneyListVersionsParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /journeys/{templateId}/publish`, but is otherwise + * the same as [JourneyService.publish]. + */ + @MustBeClosed + fun publish(templateId: String): HttpResponseFor = + publish(templateId, JourneyPublishParams.none()) + + /** @see publish */ + @MustBeClosed + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + publish(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see publish */ + @MustBeClosed + fun publish( + templateId: String, + params: JourneyPublishParams = JourneyPublishParams.none(), + ): HttpResponseFor = publish(templateId, params, RequestOptions.none()) + + /** @see publish */ + @MustBeClosed + fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see publish */ + @MustBeClosed + fun publish(params: JourneyPublishParams): HttpResponseFor = + publish(params, RequestOptions.none()) + + /** @see publish */ + @MustBeClosed + fun publish( + templateId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + publish(templateId, JourneyPublishParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /journeys/{templateId}`, but is otherwise the same + * as [JourneyService.replace]. + */ + @MustBeClosed + fun replace( + templateId: String, + params: JourneyReplaceParams, + ): HttpResponseFor = replace(templateId, params, RequestOptions.none()) + + /** @see replace */ + @MustBeClosed + fun replace( + templateId: String, + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + replace(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see replace */ + @MustBeClosed + fun replace(params: JourneyReplaceParams): HttpResponseFor = + replace(params, RequestOptions.none()) + + /** @see replace */ + @MustBeClosed + fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt index b41f4915..32d25f82 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/JourneyServiceImpl.kt @@ -5,6 +5,7 @@ package com.courier.services.blocking import com.courier.core.ClientOptions import com.courier.core.RequestOptions import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler import com.courier.core.handlers.errorBodyHandler import com.courier.core.handlers.errorHandler import com.courier.core.handlers.jsonHandler @@ -16,10 +17,20 @@ import com.courier.core.http.HttpResponseFor import com.courier.core.http.json import com.courier.core.http.parseable import com.courier.core.prepare +import com.courier.models.journeys.JourneyArchiveParams +import com.courier.models.journeys.JourneyCreateParams import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams +import com.courier.models.journeys.JourneyListVersionsParams +import com.courier.models.journeys.JourneyPublishParams +import com.courier.models.journeys.JourneyReplaceParams +import com.courier.models.journeys.JourneyResponse +import com.courier.models.journeys.JourneyRetrieveParams +import com.courier.models.journeys.JourneyVersionsListResponse import com.courier.models.journeys.JourneysInvokeResponse import com.courier.models.journeys.JourneysListResponse +import com.courier.services.blocking.journeys.TemplateService +import com.courier.services.blocking.journeys.TemplateServiceImpl import java.util.function.Consumer import kotlin.jvm.optionals.getOrNull @@ -30,11 +41,29 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO WithRawResponseImpl(clientOptions) } + private val templates: TemplateService by lazy { TemplateServiceImpl(clientOptions) } + override fun withRawResponse(): JourneyService.WithRawResponse = withRawResponse override fun withOptions(modifier: Consumer): JourneyService = JourneyServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + override fun templates(): TemplateService = templates + + override fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions, + ): JourneyResponse = + // post /journeys + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions, + ): JourneyResponse = + // get /journeys/{templateId} + withRawResponse().retrieve(params, requestOptions).parse() + override fun list( params: JourneyListParams, requestOptions: RequestOptions, @@ -42,6 +71,11 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO // get /journeys withRawResponse().list(params, requestOptions).parse() + override fun archive(params: JourneyArchiveParams, requestOptions: RequestOptions) { + // delete /journeys/{templateId} + withRawResponse().archive(params, requestOptions) + } + override fun invoke( params: JourneyInvokeParams, requestOptions: RequestOptions, @@ -49,12 +83,37 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO // post /journeys/{templateId}/invoke withRawResponse().invoke(params, requestOptions).parse() + override fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions, + ): JourneyVersionsListResponse = + // get /journeys/{templateId}/versions + withRawResponse().listVersions(params, requestOptions).parse() + + override fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions, + ): JourneyResponse = + // post /journeys/{templateId}/publish + withRawResponse().publish(params, requestOptions).parse() + + override fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions, + ): JourneyResponse = + // put /journeys/{templateId} + withRawResponse().replace(params, requestOptions).parse() + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : JourneyService.WithRawResponse { private val errorHandler: Handler = errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + private val templates: TemplateService.WithRawResponse by lazy { + TemplateServiceImpl.WithRawResponseImpl(clientOptions) + } + override fun withOptions( modifier: Consumer ): JourneyService.WithRawResponse = @@ -62,6 +121,66 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO clientOptions.toBuilder().apply(modifier::accept).build() ) + override fun templates(): TemplateService.WithRawResponse = templates + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: JourneyCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: JourneyRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + private val listHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -89,6 +208,30 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO } } + private val archiveHandler: Handler = emptyHandler() + + override fun archive( + params: JourneyArchiveParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0)) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { archiveHandler.handle(it) } + } + } + private val invokeHandler: Handler = jsonHandler(clientOptions.jsonMapper) @@ -119,5 +262,97 @@ class JourneyServiceImpl internal constructor(private val clientOptions: ClientO } } } + + private val listVersionsHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listVersions( + params: JourneyListVersionsParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "versions") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listVersionsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val publishHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun publish( + params: JourneyPublishParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "publish") + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { publishHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val replaceHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun replace( + params: JourneyReplaceParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0)) + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { replaceHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } } } diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateService.kt new file mode 100644 index 00000000..eccf81d6 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateService.kt @@ -0,0 +1,462 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.journeys + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponseFor +import com.courier.models.journeys.JourneyTemplateGetResponse +import com.courier.models.journeys.JourneyTemplateListResponse +import com.courier.models.journeys.templates.TemplateArchiveParams +import com.courier.models.journeys.templates.TemplateCreateParams +import com.courier.models.journeys.templates.TemplateListParams +import com.courier.models.journeys.templates.TemplateListVersionsParams +import com.courier.models.journeys.templates.TemplatePublishParams +import com.courier.models.journeys.templates.TemplateReplaceParams +import com.courier.models.journeys.templates.TemplateRetrieveParams +import com.courier.models.notifications.NotificationTemplateVersionListResponse +import com.google.errorprone.annotations.MustBeClosed +import java.util.function.Consumer + +interface TemplateService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): TemplateService + + /** + * Create a notification template scoped to this journey. Defaults to `DRAFT` state; pass + * `state: "PUBLISHED"` to publish on create. + */ + fun create(templateId: String, params: TemplateCreateParams): JourneyTemplateGetResponse = + create(templateId, params, RequestOptions.none()) + + /** @see create */ + fun create( + templateId: String, + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateGetResponse = + create(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see create */ + fun create(params: TemplateCreateParams): JourneyTemplateGetResponse = + create(params, RequestOptions.none()) + + /** @see create */ + fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateGetResponse + + /** + * Fetch a journey-scoped notification template by id. Pass `?version=draft` (default + * `published`) to retrieve the working draft, or `?version=vN` for a historical version. + */ + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + ): JourneyTemplateGetResponse = retrieve(notificationId, params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateGetResponse = + retrieve(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve(params: TemplateRetrieveParams): JourneyTemplateGetResponse = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateGetResponse + + /** + * List notification templates scoped to this journey. Journey-scoped notification templates can + * only be referenced from `send` nodes within the same journey. + */ + fun list(templateId: String): JourneyTemplateListResponse = + list(templateId, TemplateListParams.none()) + + /** @see list */ + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateListResponse = + list(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see list */ + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + ): JourneyTemplateListResponse = list(templateId, params, RequestOptions.none()) + + /** @see list */ + fun list( + params: TemplateListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateListResponse + + /** @see list */ + fun list(params: TemplateListParams): JourneyTemplateListResponse = + list(params, RequestOptions.none()) + + /** @see list */ + fun list(templateId: String, requestOptions: RequestOptions): JourneyTemplateListResponse = + list(templateId, TemplateListParams.none(), requestOptions) + + /** Archive the journey-scoped notification template. Archived templates cannot be sent. */ + fun archive(notificationId: String, params: TemplateArchiveParams) = + archive(notificationId, params, RequestOptions.none()) + + /** @see archive */ + fun archive( + notificationId: String, + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) = archive(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see archive */ + fun archive(params: TemplateArchiveParams) = archive(params, RequestOptions.none()) + + /** @see archive */ + fun archive( + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** + * List published versions of the journey-scoped notification template, ordered most recent + * first. + */ + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + ): NotificationTemplateVersionListResponse = + listVersions(notificationId, params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): NotificationTemplateVersionListResponse = + listVersions(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see listVersions */ + fun listVersions(params: TemplateListVersionsParams): NotificationTemplateVersionListResponse = + listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): NotificationTemplateVersionListResponse + + /** + * Publish the current draft of the journey-scoped notification template as a new version. + * Optionally roll back to a prior version by passing `{ "version": "vN" }`. + */ + fun publish(notificationId: String, params: TemplatePublishParams) = + publish(notificationId, params, RequestOptions.none()) + + /** @see publish */ + fun publish( + notificationId: String, + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) = publish(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see publish */ + fun publish(params: TemplatePublishParams) = publish(params, RequestOptions.none()) + + /** @see publish */ + fun publish( + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** Replace the journey-scoped notification template draft. */ + fun replace(notificationId: String, params: TemplateReplaceParams): JourneyTemplateGetResponse = + replace(notificationId, params, RequestOptions.none()) + + /** @see replace */ + fun replace( + notificationId: String, + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateGetResponse = + replace(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see replace */ + fun replace(params: TemplateReplaceParams): JourneyTemplateGetResponse = + replace(params, RequestOptions.none()) + + /** @see replace */ + fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): JourneyTemplateGetResponse + + /** A view of [TemplateService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: Consumer): TemplateService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /journeys/{templateId}/templates`, but is otherwise + * the same as [TemplateService.create]. + */ + @MustBeClosed + fun create( + templateId: String, + params: TemplateCreateParams, + ): HttpResponseFor = + create(templateId, params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + templateId: String, + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create(params: TemplateCreateParams): HttpResponseFor = + create(params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}/templates/{notificationId}`, + * but is otherwise the same as [TemplateService.retrieve]. + */ + @MustBeClosed + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + ): HttpResponseFor = + retrieve(notificationId, params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + notificationId: String, + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve(params: TemplateRetrieveParams): HttpResponseFor = + retrieve(params, RequestOptions.none()) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `get /journeys/{templateId}/templates`, but is otherwise + * the same as [TemplateService.list]. + */ + @MustBeClosed + fun list(templateId: String): HttpResponseFor = + list(templateId, TemplateListParams.none()) + + /** @see list */ + @MustBeClosed + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + list(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see list */ + @MustBeClosed + fun list( + templateId: String, + params: TemplateListParams = TemplateListParams.none(), + ): HttpResponseFor = + list(templateId, params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + params: TemplateListParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see list */ + @MustBeClosed + fun list(params: TemplateListParams): HttpResponseFor = + list(params, RequestOptions.none()) + + /** @see list */ + @MustBeClosed + fun list( + templateId: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + list(templateId, TemplateListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete + * /journeys/{templateId}/templates/{notificationId}`, but is otherwise the same as + * [TemplateService.archive]. + */ + @MustBeClosed + fun archive(notificationId: String, params: TemplateArchiveParams): HttpResponse = + archive(notificationId, params, RequestOptions.none()) + + /** @see archive */ + @MustBeClosed + fun archive( + notificationId: String, + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = + archive(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see archive */ + @MustBeClosed + fun archive(params: TemplateArchiveParams): HttpResponse = + archive(params, RequestOptions.none()) + + /** @see archive */ + @MustBeClosed + fun archive( + params: TemplateArchiveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** + * Returns a raw HTTP response for `get + * /journeys/{templateId}/templates/{notificationId}/versions`, but is otherwise the same as + * [TemplateService.listVersions]. + */ + @MustBeClosed + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + ): HttpResponseFor = + listVersions(notificationId, params, RequestOptions.none()) + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + notificationId: String, + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + listVersions(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + params: TemplateListVersionsParams + ): HttpResponseFor = + listVersions(params, RequestOptions.none()) + + /** @see listVersions */ + @MustBeClosed + fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** + * Returns a raw HTTP response for `post + * /journeys/{templateId}/templates/{notificationId}/publish`, but is otherwise the same as + * [TemplateService.publish]. + */ + @MustBeClosed + fun publish(notificationId: String, params: TemplatePublishParams): HttpResponse = + publish(notificationId, params, RequestOptions.none()) + + /** @see publish */ + @MustBeClosed + fun publish( + notificationId: String, + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = + publish(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see publish */ + @MustBeClosed + fun publish(params: TemplatePublishParams): HttpResponse = + publish(params, RequestOptions.none()) + + /** @see publish */ + @MustBeClosed + fun publish( + params: TemplatePublishParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** + * Returns a raw HTTP response for `put /journeys/{templateId}/templates/{notificationId}`, + * but is otherwise the same as [TemplateService.replace]. + */ + @MustBeClosed + fun replace( + notificationId: String, + params: TemplateReplaceParams, + ): HttpResponseFor = + replace(notificationId, params, RequestOptions.none()) + + /** @see replace */ + @MustBeClosed + fun replace( + notificationId: String, + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + replace(params.toBuilder().notificationId(notificationId).build(), requestOptions) + + /** @see replace */ + @MustBeClosed + fun replace(params: TemplateReplaceParams): HttpResponseFor = + replace(params, RequestOptions.none()) + + /** @see replace */ + @MustBeClosed + fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateServiceImpl.kt new file mode 100644 index 00000000..625feac0 --- /dev/null +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/journeys/TemplateServiceImpl.kt @@ -0,0 +1,330 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.journeys + +import com.courier.core.ClientOptions +import com.courier.core.RequestOptions +import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler +import com.courier.core.handlers.errorBodyHandler +import com.courier.core.handlers.errorHandler +import com.courier.core.handlers.jsonHandler +import com.courier.core.http.HttpMethod +import com.courier.core.http.HttpRequest +import com.courier.core.http.HttpResponse +import com.courier.core.http.HttpResponse.Handler +import com.courier.core.http.HttpResponseFor +import com.courier.core.http.json +import com.courier.core.http.parseable +import com.courier.core.prepare +import com.courier.models.journeys.JourneyTemplateGetResponse +import com.courier.models.journeys.JourneyTemplateListResponse +import com.courier.models.journeys.templates.TemplateArchiveParams +import com.courier.models.journeys.templates.TemplateCreateParams +import com.courier.models.journeys.templates.TemplateListParams +import com.courier.models.journeys.templates.TemplateListVersionsParams +import com.courier.models.journeys.templates.TemplatePublishParams +import com.courier.models.journeys.templates.TemplateReplaceParams +import com.courier.models.journeys.templates.TemplateRetrieveParams +import com.courier.models.notifications.NotificationTemplateVersionListResponse +import java.util.function.Consumer +import kotlin.jvm.optionals.getOrNull + +class TemplateServiceImpl internal constructor(private val clientOptions: ClientOptions) : + TemplateService { + + private val withRawResponse: TemplateService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): TemplateService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: Consumer): TemplateService = + TemplateServiceImpl(clientOptions.toBuilder().apply(modifier::accept).build()) + + override fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions, + ): JourneyTemplateGetResponse = + // post /journeys/{templateId}/templates + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions, + ): JourneyTemplateGetResponse = + // get /journeys/{templateId}/templates/{notificationId} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun list( + params: TemplateListParams, + requestOptions: RequestOptions, + ): JourneyTemplateListResponse = + // get /journeys/{templateId}/templates + withRawResponse().list(params, requestOptions).parse() + + override fun archive(params: TemplateArchiveParams, requestOptions: RequestOptions) { + // delete /journeys/{templateId}/templates/{notificationId} + withRawResponse().archive(params, requestOptions) + } + + override fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions, + ): NotificationTemplateVersionListResponse = + // get /journeys/{templateId}/templates/{notificationId}/versions + withRawResponse().listVersions(params, requestOptions).parse() + + override fun publish(params: TemplatePublishParams, requestOptions: RequestOptions) { + // post /journeys/{templateId}/templates/{notificationId}/publish + withRawResponse().publish(params, requestOptions) + } + + override fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions, + ): JourneyTemplateGetResponse = + // put /journeys/{templateId}/templates/{notificationId} + withRawResponse().replace(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + TemplateService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: Consumer + ): TemplateService.WithRawResponse = + TemplateServiceImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier::accept).build() + ) + + private val createHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: TemplateCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "templates") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: TemplateRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun list( + params: TemplateListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("journeys", params._pathParam(0), "templates") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val archiveHandler: Handler = emptyHandler() + + override fun archive( + params: TemplateArchiveParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { archiveHandler.handle(it) } + } + } + + private val listVersionsHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listVersions( + params: TemplateListVersionsParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + "versions", + ) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listVersionsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val publishHandler: Handler = emptyHandler() + + override fun publish( + params: TemplatePublishParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + "publish", + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { publishHandler.handle(it) } + } + } + + private val replaceHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun replace( + params: TemplateReplaceParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("notificationId", params.notificationId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "journeys", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { replaceHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt index 77c3b221..e5174142 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateService.kt @@ -4,10 +4,12 @@ package com.courier.services.blocking.tenants import com.courier.core.ClientOptions import com.courier.core.RequestOptions +import com.courier.core.http.HttpResponse import com.courier.core.http.HttpResponseFor import com.courier.models.tenants.BaseTemplateTenantAssociation import com.courier.models.tenants.PostTenantTemplatePublishResponse import com.courier.models.tenants.PutTenantTemplateResponse +import com.courier.models.tenants.templates.TemplateDeleteParams import com.courier.models.tenants.templates.TemplateListParams import com.courier.models.tenants.templates.TemplateListResponse import com.courier.models.tenants.templates.TemplatePublishParams @@ -86,6 +88,30 @@ interface TemplateService { fun list(tenantId: String, requestOptions: RequestOptions): TemplateListResponse = list(tenantId, TemplateListParams.none(), requestOptions) + /** + * Deletes the tenant's notification template with the given `template_id`. + * + * Returns **204 No Content** with an empty body on success. + * + * Returns **404** if there is no template with this ID for the tenant, including a second + * `DELETE` after a successful removal. + */ + fun delete(templateId: String, params: TemplateDeleteParams) = + delete(templateId, params, RequestOptions.none()) + + /** @see delete */ + fun delete( + templateId: String, + params: TemplateDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see delete */ + fun delete(params: TemplateDeleteParams) = delete(params, RequestOptions.none()) + + /** @see delete */ + fun delete(params: TemplateDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + /** * Publishes a specific version of a notification template for a tenant. * @@ -233,6 +259,34 @@ interface TemplateService { ): HttpResponseFor = list(tenantId, TemplateListParams.none(), requestOptions) + /** + * Returns a raw HTTP response for `delete /tenants/{tenant_id}/templates/{template_id}`, + * but is otherwise the same as [TemplateService.delete]. + */ + @MustBeClosed + fun delete(templateId: String, params: TemplateDeleteParams): HttpResponse = + delete(templateId, params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + templateId: String, + params: TemplateDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().templateId(templateId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete(params: TemplateDeleteParams): HttpResponse = + delete(params, RequestOptions.none()) + + /** @see delete */ + @MustBeClosed + fun delete( + params: TemplateDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + /** * Returns a raw HTTP response for `post * /tenants/{tenant_id}/templates/{template_id}/publish`, but is otherwise the same as diff --git a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt index 739d1073..261e3622 100644 --- a/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt +++ b/courier-java-core/src/main/kotlin/com/courier/services/blocking/tenants/TemplateServiceImpl.kt @@ -5,6 +5,7 @@ package com.courier.services.blocking.tenants import com.courier.core.ClientOptions import com.courier.core.RequestOptions import com.courier.core.checkRequired +import com.courier.core.handlers.emptyHandler import com.courier.core.handlers.errorBodyHandler import com.courier.core.handlers.errorHandler import com.courier.core.handlers.jsonHandler @@ -19,6 +20,7 @@ import com.courier.core.prepare import com.courier.models.tenants.BaseTemplateTenantAssociation import com.courier.models.tenants.PostTenantTemplatePublishResponse import com.courier.models.tenants.PutTenantTemplateResponse +import com.courier.models.tenants.templates.TemplateDeleteParams import com.courier.models.tenants.templates.TemplateListParams import com.courier.models.tenants.templates.TemplateListResponse import com.courier.models.tenants.templates.TemplatePublishParams @@ -59,6 +61,11 @@ class TemplateServiceImpl internal constructor(private val clientOptions: Client // get /tenants/{tenant_id}/templates withRawResponse().list(params, requestOptions).parse() + override fun delete(params: TemplateDeleteParams, requestOptions: RequestOptions) { + // delete /tenants/{tenant_id}/templates/{template_id} + withRawResponse().delete(params, requestOptions) + } + override fun publish( params: TemplatePublishParams, requestOptions: RequestOptions, @@ -157,6 +164,35 @@ class TemplateServiceImpl internal constructor(private val clientOptions: Client } } + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: TemplateDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("templateId", params.templateId().getOrNull()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments( + "tenants", + params._pathParam(0), + "templates", + params._pathParam(1), + ) + .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + private val publishHandler: Handler = jsonHandler(clientOptions.jsonMapper) diff --git a/courier-java-core/src/test/kotlin/com/courier/core/http/LoggingHttpClientTest.kt b/courier-java-core/src/test/kotlin/com/courier/core/http/LoggingHttpClientTest.kt new file mode 100644 index 00000000..56ea5cec --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/core/http/LoggingHttpClientTest.kt @@ -0,0 +1,1000 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.core.http + +import com.courier.core.LogLevel +import com.courier.core.RequestOptions +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream +import java.io.PrintStream +import java.nio.charset.StandardCharsets +import java.time.Clock +import java.time.Instant +import java.time.ZoneOffset +import java.util.concurrent.CompletableFuture +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.parallel.ResourceLock +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +@ResourceLock("stderr") +internal class LoggingHttpClientTest { + + private lateinit var originalErr: PrintStream + private lateinit var errContent: ByteArrayOutputStream + + @BeforeEach + fun beforeEach() { + originalErr = System.err + errContent = ByteArrayOutputStream() + System.setErr(PrintStream(errContent)) + } + + @AfterEach + fun afterEach() { + System.setErr(originalErr) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun offLevel_noOutput(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.OFF) + + val response = client.execute(simpleGetRequest(), async).apply { body().readBytes() } + + assertThat(response.statusCode()).isEqualTo(200) + assertThat(stderrOutput()).isEmpty() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsGetRequest(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.INFO) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsPostRequestWithBodySize(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.INFO) + + client.execute(postRequestWithBody("""{"key":"value"}"""), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> POST https://api.example.com/v1/resources (15-byte body) + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsRequestWithUnknownLengthBody(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.INFO) + + client + .execute(postRequestWithBody("""{"key":"value"}""", contentLength = -1L), async) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> POST https://api.example.com/v1/resources (unknown-length body) + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsResponseStatusAndDuration(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:00:01.234Z"), + ) + val client = loggingClient(fakeHttpClient(statusCode = 201), LogLevel.INFO, clock) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 201 (1s 234ms) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsResponseContentLength(async: Boolean) { + val headers = + Headers.builder().put("Content-Length", "42").put("Content-Type", "text/plain").build() + val client = loggingClient(fakeHttpClient(responseHeaders = headers), LogLevel.INFO) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (0s, 42-byte body) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_doesNotLogHeaders(async: Boolean) { + val headers = Headers.builder().put("X-Custom", "visible").build() + val client = loggingClient(fakeHttpClient(responseHeaders = headers), LogLevel.INFO) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("v1") + .putHeader("X-Request-Custom", "req-value") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1 + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsGetWithEndMarker(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.DEBUG) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsRequestAndResponseHeaders(async: Boolean) { + val responseHeaders = + Headers.builder() + .put("X-Response-Id", "abc-123") + .put("Content-Type", "text/plain") + .build() + val client = + loggingClient(fakeHttpClient(responseHeaders = responseHeaders), LogLevel.DEBUG) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("test") + .putHeader("X-Custom", "my-value") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/test + |X-Custom: my-value + |--> END GET + | + |<-- 200 (0s) + |Content-Type: text/plain + |X-Response-Id: abc-123 + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_redactsSensitiveHeaders(async: Boolean) { + val client = + loggingClient( + fakeHttpClient(), + LogLevel.DEBUG, + redactedHeaders = setOf("Authorization", "X-Secret"), + ) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("test") + .putHeader("Authorization", "Bearer token-123") + .putHeader("X-Secret", "secret-value") + .putHeader("X-Public", "public-value") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/test + |Authorization: ██ + |X-Public: public-value + |X-Secret: ██ + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_redactsHeadersCaseInsensitively(async: Boolean) { + val client = + loggingClient( + fakeHttpClient(), + LogLevel.DEBUG, + redactedHeaders = setOf("Authorization"), + ) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("test") + .putHeader("authorization", "Bearer secret") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/test + |authorization: ██ + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsRequestBody(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.DEBUG) + val body = """{"name":"test","value":42}""" + + client.execute(postRequestWithBody(body), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> POST https://api.example.com/v1/resources (26-byte body) + | + |{"name":"test","value":42} + |--> END POST (26-byte body) + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsResponseBody(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + val response = client.execute(simpleGetRequest(), async) + val body = response.body().readBytes().toString(StandardCharsets.UTF_8) + + assertThat(body).isEqualTo(responseBody) + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + | + |{"id":1,"status":"ok"} + |<-- END HTTP (22-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsBinaryResponseBodyAsOmitted(async: Boolean) { + val binaryBody = ByteArray(256) { it.toByte() } + val client = loggingClient(fakeHttpClient(responseBody = binaryBody), LogLevel.DEBUG) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + | + |(binary body omitted) + |<-- END HTTP (256-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsMultilineResponseBody(async: Boolean) { + val multilineBody = "line1\nline2\nline3" + val headers = Headers.builder().put("Content-Type", "text/plain; charset=utf-8").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = multilineBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: text/plain; charset=utf-8 + | + |line1 + |line2 + |line3 + |<-- END HTTP (17-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsResponseBodyWithExplicitCharset(async: Boolean) { + val responseBody = "héllo wörld" + val headers = Headers.builder().put("Content-Type", "text/plain; charset=utf-8").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: text/plain; charset=utf-8 + | + |héllo wörld + |<-- END HTTP (13-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsResponseBodyWithNoContentType(async: Boolean) { + val responseBody = "plain text body" + val client = + loggingClient( + fakeHttpClient(responseBody = responseBody.toByteArray(StandardCharsets.UTF_8)), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + | + |plain text body + |<-- END HTTP (15-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEmptyResponseBody(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.DEBUG) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEndHttpMarkerOnEarlyClose(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + val body = client.execute(simpleGetRequest(), async).body() + body.read(ByteArray(5)) + body.close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + | + |{"id" + |<-- END HTTP (5-byte body, closed early) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEndHttpMarkerOnCloseWithoutReading(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + |<-- END HTTP (0-byte body, closed early) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEndHttpMarkerWhenResponseClosedAfterPartialRead(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + val response = client.execute(simpleGetRequest(), async) + response.body().read(ByteArray(5)) + response.close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + | + |{"id" + |<-- END HTTP (5-byte body, closed early) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_doesNotLogEndHttpMarkerWhenResponseClosedWithoutBodyAccess(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun errorLevel_logsRequestFailure(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:00:01.234Z"), + ) + val client = + loggingClient( + failingHttpClient(IOException("Connection refused")), + LogLevel.ERROR, + clock, + ) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- !! IOException: Connection refused (1s 234ms) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_doesNotLogRequestFailure(async: Boolean) { + val client = + loggingClient(failingHttpClient(IOException("Connection refused")), LogLevel.INFO) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsRequestFailureAfterHeaders(async: Boolean) { + val client = + loggingClient(failingHttpClient(IOException("Connection refused")), LogLevel.DEBUG) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- !! IOException: Connection refused (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun errorLevel_logsRequestFailureWithoutMessage(async: Boolean) { + val client = loggingClient(failingHttpClient(IOException()), LogLevel.ERROR) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- !! IOException (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun offLevel_doesNotLogRequestFailure(async: Boolean) { + val client = + loggingClient(failingHttpClient(IOException("Connection refused")), LogLevel.OFF) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()).isEmpty() + } + + @Test + fun errorLevel_logsExecuteAsyncSynchronousThrow() { + val error = IOException("Connection refused") + val client = + loggingClient( + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = throw UnsupportedOperationException() + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture = throw error + + override fun close() {} + }, + LogLevel.ERROR, + ) + + assertThatThrownBy { client.execute(simpleGetRequest(), async = true) }.isSameAs(error) + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- !! IOException: Connection refused (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun durationFormat_seconds(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:00:02.500Z"), + ) + val client = loggingClient(fakeHttpClient(), LogLevel.INFO, clock) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (2s 500ms) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun durationFormat_minutesAndSeconds(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:01:40.467Z"), + ) + val client = loggingClient(fakeHttpClient(), LogLevel.INFO, clock) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (1m 40s 467ms) + |""" + .trimMargin() + ) + } + + @Test + fun builder_toBuilder_roundtrips() { + val delegate = fakeHttpClient() + val clock = Clock.fixed(Instant.parse("1998-04-21T00:00:00Z"), ZoneOffset.UTC) + val client = + LoggingHttpClient.builder() + .httpClient(delegate) + .level(LogLevel.DEBUG) + .redactedHeaders(setOf("X-Secret")) + .clock(clock) + .build() + + val rebuilt = client.toBuilder().build() + + assertThat(rebuilt.httpClient).isSameAs(delegate) + assertThat(rebuilt.level).isEqualTo(LogLevel.DEBUG) + assertThat(rebuilt.redactedHeaders).containsExactly("X-Secret") + assertThat(rebuilt.clock).isEqualTo(clock) + } + + @Test + fun close_delegatesToUnderlyingClient() { + var closed = false + val delegate = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = throw UnsupportedOperationException() + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture = throw UnsupportedOperationException() + + override fun close() { + closed = true + } + } + val client = loggingClient(delegate, LogLevel.OFF) + + client.close() + + assertThat(closed).isTrue() + } + + private fun stderrOutput(): String = errContent.toString("UTF-8") + + private fun loggingClient( + httpClient: HttpClient, + level: LogLevel, + clock: Clock = clockFrom(Instant.parse("1998-04-21T00:00:00Z")), + redactedHeaders: Set = + setOf("authorization", "api-key", "x-api-key", "cookie", "set-cookie"), + ): LoggingHttpClient = + LoggingHttpClient.builder() + .httpClient(httpClient) + .level(level) + .clock(clock) + .redactedHeaders(redactedHeaders) + .build() + + private fun simpleGetRequest(): HttpRequest = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("v1") + .addPathSegment("resources") + .build() + + private fun postRequestWithBody( + body: String, + contentType: String = "application/json", + contentLength: Long? = null, + ): HttpRequest = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl("https://api.example.com") + .addPathSegment("v1") + .addPathSegment("resources") + .body( + object : HttpRequestBody { + private val bytes = body.toByteArray(StandardCharsets.UTF_8) + + override fun writeTo(outputStream: OutputStream) { + outputStream.write(bytes) + } + + override fun contentType(): String = contentType + + override fun contentLength(): Long = contentLength ?: bytes.size.toLong() + + override fun repeatable(): Boolean = true + + override fun close() {} + } + ) + .build() + + private fun fakeHttpClient( + statusCode: Int = 200, + responseHeaders: Headers = Headers.builder().build(), + responseBody: ByteArray = ByteArray(0), + ): HttpClient = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + // Consume the request body if present to trigger logging. + request.body?.let { + val out = ByteArrayOutputStream() + it.writeTo(out) + } + return fakeResponse(statusCode, responseHeaders, responseBody) + } + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture = + CompletableFuture.completedFuture(execute(request, requestOptions)) + + override fun close() {} + } + + private fun failingHttpClient(error: Throwable): HttpClient = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + request.body?.let { + val out = ByteArrayOutputStream() + it.writeTo(out) + } + throw error + } + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture { + val future = CompletableFuture() + future.completeExceptionally(error) + return future + } + + override fun close() {} + } + + private fun fakeResponse(statusCode: Int, headers: Headers, body: ByteArray): HttpResponse = + object : HttpResponse { + override fun statusCode(): Int = statusCode + + override fun headers(): Headers = headers + + override fun body(): InputStream = ByteArrayInputStream(body) + + override fun close() {} + } + + private fun clockFrom(vararg instants: Instant): Clock = + object : Clock() { + private var index = 0 + + override fun getZone() = ZoneOffset.UTC + + override fun withZone(zone: java.time.ZoneId?) = this + + override fun instant(): Instant { + val instant = instants[index % instants.size] + index++ + return instant + } + } + + private fun HttpClient.execute(request: HttpRequest, async: Boolean): HttpResponse = + if (async) executeAsync(request).get() else execute(request) +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/CreateJourneyRequestTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/CreateJourneyRequestTest.kt new file mode 100644 index 00000000..3f732372 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/CreateJourneyRequestTest.kt @@ -0,0 +1,87 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class CreateJourneyRequestTest { + + @Test + fun create() { + val createJourneyRequest = + CreateJourneyRequest.builder() + .name("x") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + + assertThat(createJourneyRequest.name()).isEqualTo("x") + assertThat(createJourneyRequest.nodes()) + .containsExactly( + JourneyNode.ofApiInvokeTrigger( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + ) + assertThat(createJourneyRequest.enabled()).contains(true) + assertThat(createJourneyRequest.state()).contains(JourneyState.DRAFT) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val createJourneyRequest = + CreateJourneyRequest.builder() + .name("x") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + + val roundtrippedCreateJourneyRequest = + jsonMapper.readValue( + jsonMapper.writeValueAsString(createJourneyRequest), + jacksonTypeRef(), + ) + + assertThat(roundtrippedCreateJourneyRequest).isEqualTo(createJourneyRequest) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyAiNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyAiNodeTest.kt new file mode 100644 index 00000000..9b206c96 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyAiNodeTest.kt @@ -0,0 +1,71 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyAiNodeTest { + + @Test + fun create() { + val journeyAiNode = + JourneyAiNode.builder() + .outputSchema( + JourneyAiNode.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .type(JourneyAiNode.Type.AI) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .model("x") + .userPrompt("user_prompt") + .webSearch(true) + .build() + + assertThat(journeyAiNode.outputSchema()) + .isEqualTo( + JourneyAiNode.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + assertThat(journeyAiNode.type()).isEqualTo(JourneyAiNode.Type.AI) + assertThat(journeyAiNode.id()).contains("x") + assertThat(journeyAiNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + assertThat(journeyAiNode.model()).contains("x") + assertThat(journeyAiNode.userPrompt()).contains("user_prompt") + assertThat(journeyAiNode.webSearch()).contains(true) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyAiNode = + JourneyAiNode.builder() + .outputSchema( + JourneyAiNode.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .type(JourneyAiNode.Type.AI) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .model("x") + .userPrompt("user_prompt") + .webSearch(true) + .build() + + val roundtrippedJourneyAiNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyAiNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyAiNode).isEqualTo(journeyAiNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyApiInvokeTriggerNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyApiInvokeTriggerNodeTest.kt new file mode 100644 index 00000000..c24357c7 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyApiInvokeTriggerNodeTest.kt @@ -0,0 +1,67 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyApiInvokeTriggerNodeTest { + + @Test + fun create() { + val journeyApiInvokeTriggerNode = + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + assertThat(journeyApiInvokeTriggerNode.triggerType()) + .isEqualTo(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + assertThat(journeyApiInvokeTriggerNode.type()) + .isEqualTo(JourneyApiInvokeTriggerNode.Type.TRIGGER) + assertThat(journeyApiInvokeTriggerNode.id()).contains("x") + assertThat(journeyApiInvokeTriggerNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + assertThat(journeyApiInvokeTriggerNode.schema()) + .contains( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyApiInvokeTriggerNode = + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val roundtrippedJourneyApiInvokeTriggerNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyApiInvokeTriggerNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyApiInvokeTriggerNode).isEqualTo(journeyApiInvokeTriggerNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyArchiveParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyArchiveParamsTest.kt new file mode 100644 index 00000000..aa54951a --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyArchiveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyArchiveParamsTest { + + @Test + fun create() { + JourneyArchiveParams.builder().templateId("x").build() + } + + @Test + fun pathParams() { + val params = JourneyArchiveParams.builder().templateId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionGroupTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionGroupTest.kt new file mode 100644 index 00000000..7ce7295a --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionGroupTest.kt @@ -0,0 +1,48 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyConditionGroupTest { + + @Test + fun create() { + val journeyConditionGroup = + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + + assertThat(journeyConditionGroup.and().getOrNull()) + .containsExactly(listOf("string", "string"), listOf("string", "string")) + assertThat(journeyConditionGroup.or().getOrNull()) + .containsExactly(listOf("string", "string"), listOf("string", "string")) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyConditionGroup = + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + + val roundtrippedJourneyConditionGroup = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyConditionGroup), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyConditionGroup).isEqualTo(journeyConditionGroup) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionNestedGroupTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionNestedGroupTest.kt new file mode 100644 index 00000000..4ea8ce31 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionNestedGroupTest.kt @@ -0,0 +1,130 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyConditionNestedGroupTest { + + @Test + fun create() { + val journeyConditionNestedGroup = + JourneyConditionNestedGroup.builder() + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .build() + + assertThat(journeyConditionNestedGroup.and().getOrNull()) + .containsExactly( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build(), + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build(), + ) + assertThat(journeyConditionNestedGroup.or().getOrNull()) + .containsExactly( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build(), + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build(), + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyConditionNestedGroup = + JourneyConditionNestedGroup.builder() + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .build() + + val roundtrippedJourneyConditionNestedGroup = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyConditionNestedGroup), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyConditionNestedGroup).isEqualTo(journeyConditionNestedGroup) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionsFieldTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionsFieldTest.kt new file mode 100644 index 00000000..9d911c1f --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyConditionsFieldTest.kt @@ -0,0 +1,194 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.courier.errors.CourierInvalidDataException +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 JourneyConditionsFieldTest { + + @Test + fun ofConditionAtom() { + val conditionAtom = listOf("string", "string") + + val journeyConditionsField = JourneyConditionsField.ofConditionAtom(conditionAtom) + + assertThat(journeyConditionsField.conditionAtom()).contains(conditionAtom) + assertThat(journeyConditionsField.conditionGroup()).isEmpty + assertThat(journeyConditionsField.conditionNestedGroup()).isEmpty + } + + @Test + fun ofConditionAtomRoundtrip() { + val jsonMapper = jsonMapper() + val journeyConditionsField = + JourneyConditionsField.ofConditionAtom(listOf("string", "string")) + + val roundtrippedJourneyConditionsField = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyConditionsField), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyConditionsField).isEqualTo(journeyConditionsField) + } + + @Test + fun ofConditionGroup() { + val conditionGroup = + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + + val journeyConditionsField = JourneyConditionsField.ofConditionGroup(conditionGroup) + + assertThat(journeyConditionsField.conditionAtom()).isEmpty + assertThat(journeyConditionsField.conditionGroup()).contains(conditionGroup) + assertThat(journeyConditionsField.conditionNestedGroup()).isEmpty + } + + @Test + fun ofConditionGroupRoundtrip() { + val jsonMapper = jsonMapper() + val journeyConditionsField = + JourneyConditionsField.ofConditionGroup( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + + val roundtrippedJourneyConditionsField = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyConditionsField), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyConditionsField).isEqualTo(journeyConditionsField) + } + + @Test + fun ofConditionNestedGroup() { + val conditionNestedGroup = + JourneyConditionNestedGroup.builder() + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .build() + + val journeyConditionsField = + JourneyConditionsField.ofConditionNestedGroup(conditionNestedGroup) + + assertThat(journeyConditionsField.conditionAtom()).isEmpty + assertThat(journeyConditionsField.conditionGroup()).isEmpty + assertThat(journeyConditionsField.conditionNestedGroup()).contains(conditionNestedGroup) + } + + @Test + fun ofConditionNestedGroupRoundtrip() { + val jsonMapper = jsonMapper() + val journeyConditionsField = + JourneyConditionsField.ofConditionNestedGroup( + JourneyConditionNestedGroup.builder() + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addAnd( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .addOr( + JourneyConditionGroup.builder() + .addAnd(listOf("string", "string")) + .addAnd(listOf("string", "string")) + .addOr(listOf("string", "string")) + .addOr(listOf("string", "string")) + .build() + ) + .build() + ) + + val roundtrippedJourneyConditionsField = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyConditionsField), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyConditionsField).isEqualTo(journeyConditionsField) + } + + enum class IncompatibleJsonShapeTestCase(val value: JsonValue) { + BOOLEAN(JsonValue.from(false)), + STRING(JsonValue.from("invalid")), + INTEGER(JsonValue.from(-1)), + FLOAT(JsonValue.from(3.14)), + } + + @ParameterizedTest + @EnumSource + fun incompatibleJsonShapeDeserializesToUnknown(testCase: IncompatibleJsonShapeTestCase) { + val journeyConditionsField = + jsonMapper().convertValue(testCase.value, jacksonTypeRef()) + + val e = assertThrows { journeyConditionsField.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCreateParamsTest.kt new file mode 100644 index 00000000..af849ba6 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyCreateParamsTest.kt @@ -0,0 +1,171 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyCreateParamsTest { + + @Test + fun create() { + JourneyCreateParams.builder() + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + JourneyCreateParams.builder() + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + JourneyCreateParams.builder() + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .build() + ) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyDelayDurationNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyDelayDurationNodeTest.kt new file mode 100644 index 00000000..39ab6477 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyDelayDurationNodeTest.kt @@ -0,0 +1,52 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyDelayDurationNodeTest { + + @Test + fun create() { + val journeyDelayDurationNode = + JourneyDelayDurationNode.builder() + .duration("x") + .mode(JourneyDelayDurationNode.Mode.DURATION) + .type(JourneyDelayDurationNode.Type.DELAY) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + assertThat(journeyDelayDurationNode.duration()).isEqualTo("x") + assertThat(journeyDelayDurationNode.mode()) + .isEqualTo(JourneyDelayDurationNode.Mode.DURATION) + assertThat(journeyDelayDurationNode.type()).isEqualTo(JourneyDelayDurationNode.Type.DELAY) + assertThat(journeyDelayDurationNode.id()).contains("x") + assertThat(journeyDelayDurationNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyDelayDurationNode = + JourneyDelayDurationNode.builder() + .duration("x") + .mode(JourneyDelayDurationNode.Mode.DURATION) + .type(JourneyDelayDurationNode.Type.DELAY) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val roundtrippedJourneyDelayDurationNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyDelayDurationNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyDelayDurationNode).isEqualTo(journeyDelayDurationNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyDelayUntilNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyDelayUntilNodeTest.kt new file mode 100644 index 00000000..8045cb46 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyDelayUntilNodeTest.kt @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyDelayUntilNodeTest { + + @Test + fun create() { + val journeyDelayUntilNode = + JourneyDelayUntilNode.builder() + .mode(JourneyDelayUntilNode.Mode.UNTIL) + .type(JourneyDelayUntilNode.Type.DELAY) + .until("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + assertThat(journeyDelayUntilNode.mode()).isEqualTo(JourneyDelayUntilNode.Mode.UNTIL) + assertThat(journeyDelayUntilNode.type()).isEqualTo(JourneyDelayUntilNode.Type.DELAY) + assertThat(journeyDelayUntilNode.until()).isEqualTo("x") + assertThat(journeyDelayUntilNode.id()).contains("x") + assertThat(journeyDelayUntilNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyDelayUntilNode = + JourneyDelayUntilNode.builder() + .mode(JourneyDelayUntilNode.Mode.UNTIL) + .type(JourneyDelayUntilNode.Type.DELAY) + .until("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val roundtrippedJourneyDelayUntilNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyDelayUntilNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyDelayUntilNode).isEqualTo(journeyDelayUntilNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyExitNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyExitNodeTest.kt new file mode 100644 index 00000000..41578a66 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyExitNodeTest.kt @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyExitNodeTest { + + @Test + fun create() { + val journeyExitNode = + JourneyExitNode.builder().type(JourneyExitNode.Type.EXIT).id("x").build() + + assertThat(journeyExitNode.type()).isEqualTo(JourneyExitNode.Type.EXIT) + assertThat(journeyExitNode.id()).contains("x") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyExitNode = + JourneyExitNode.builder().type(JourneyExitNode.Type.EXIT).id("x").build() + + val roundtrippedJourneyExitNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyExitNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyExitNode).isEqualTo(journeyExitNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyFetchGetDeleteNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyFetchGetDeleteNodeTest.kt new file mode 100644 index 00000000..1e359a12 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyFetchGetDeleteNodeTest.kt @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyFetchGetDeleteNodeTest { + + @Test + fun create() { + val journeyFetchGetDeleteNode = + JourneyFetchGetDeleteNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchGetDeleteNode.Method.GET) + .type(JourneyFetchGetDeleteNode.Type.FETCH) + .url("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchGetDeleteNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchGetDeleteNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchGetDeleteNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + assertThat(journeyFetchGetDeleteNode.mergeStrategy()) + .isEqualTo(JourneyMergeStrategy.OVERWRITE) + assertThat(journeyFetchGetDeleteNode.method()) + .isEqualTo(JourneyFetchGetDeleteNode.Method.GET) + assertThat(journeyFetchGetDeleteNode.type()).isEqualTo(JourneyFetchGetDeleteNode.Type.FETCH) + assertThat(journeyFetchGetDeleteNode.url()).isEqualTo("x") + assertThat(journeyFetchGetDeleteNode.id()).contains("x") + assertThat(journeyFetchGetDeleteNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + assertThat(journeyFetchGetDeleteNode.headers()) + .contains( + JourneyFetchGetDeleteNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + assertThat(journeyFetchGetDeleteNode.queryParams()) + .contains( + JourneyFetchGetDeleteNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + assertThat(journeyFetchGetDeleteNode.responseSchema()) + .contains( + JourneyFetchGetDeleteNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyFetchGetDeleteNode = + JourneyFetchGetDeleteNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchGetDeleteNode.Method.GET) + .type(JourneyFetchGetDeleteNode.Type.FETCH) + .url("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchGetDeleteNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchGetDeleteNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchGetDeleteNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val roundtrippedJourneyFetchGetDeleteNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyFetchGetDeleteNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyFetchGetDeleteNode).isEqualTo(journeyFetchGetDeleteNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyFetchPostPutNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyFetchPostPutNodeTest.kt new file mode 100644 index 00000000..59d485f9 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyFetchPostPutNodeTest.kt @@ -0,0 +1,107 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyFetchPostPutNodeTest { + + @Test + fun create() { + val journeyFetchPostPutNode = + JourneyFetchPostPutNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchPostPutNode.Method.POST) + .type(JourneyFetchPostPutNode.Type.FETCH) + .url("x") + .id("x") + .body("body") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchPostPutNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchPostPutNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchPostPutNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + assertThat(journeyFetchPostPutNode.mergeStrategy()) + .isEqualTo(JourneyMergeStrategy.OVERWRITE) + assertThat(journeyFetchPostPutNode.method()).isEqualTo(JourneyFetchPostPutNode.Method.POST) + assertThat(journeyFetchPostPutNode.type()).isEqualTo(JourneyFetchPostPutNode.Type.FETCH) + assertThat(journeyFetchPostPutNode.url()).isEqualTo("x") + assertThat(journeyFetchPostPutNode.id()).contains("x") + assertThat(journeyFetchPostPutNode.body()).contains("body") + assertThat(journeyFetchPostPutNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + assertThat(journeyFetchPostPutNode.headers()) + .contains( + JourneyFetchPostPutNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + assertThat(journeyFetchPostPutNode.queryParams()) + .contains( + JourneyFetchPostPutNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + assertThat(journeyFetchPostPutNode.responseSchema()) + .contains( + JourneyFetchPostPutNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyFetchPostPutNode = + JourneyFetchPostPutNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchPostPutNode.Method.POST) + .type(JourneyFetchPostPutNode.Type.FETCH) + .url("x") + .id("x") + .body("body") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchPostPutNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchPostPutNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchPostPutNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val roundtrippedJourneyFetchPostPutNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyFetchPostPutNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyFetchPostPutNode).isEqualTo(journeyFetchPostPutNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyListVersionsParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyListVersionsParamsTest.kt new file mode 100644 index 00000000..af9b1dde --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyListVersionsParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyListVersionsParamsTest { + + @Test + fun create() { + JourneyListVersionsParams.builder().templateId("x").build() + } + + @Test + fun pathParams() { + val params = JourneyListVersionsParams.builder().templateId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyNodeTest.kt new file mode 100644 index 00000000..c7e441a3 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyNodeTest.kt @@ -0,0 +1,797 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.courier.errors.CourierInvalidDataException +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 JourneyNodeTest { + + @Test + fun ofApiInvokeTrigger() { + val apiInvokeTrigger = + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val journeyNode = JourneyNode.ofApiInvokeTrigger(apiInvokeTrigger) + + assertThat(journeyNode.apiInvokeTrigger()).contains(apiInvokeTrigger) + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofApiInvokeTriggerRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofApiInvokeTrigger( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofSegmentTrigger() { + val segmentTrigger = + JourneySegmentTriggerNode.builder() + .requestType(JourneySegmentTriggerNode.RequestType.IDENTIFY) + .triggerType(JourneySegmentTriggerNode.TriggerType.SEGMENT) + .type(JourneySegmentTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .eventId("x") + .build() + + val journeyNode = JourneyNode.ofSegmentTrigger(segmentTrigger) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).contains(segmentTrigger) + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofSegmentTriggerRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofSegmentTrigger( + JourneySegmentTriggerNode.builder() + .requestType(JourneySegmentTriggerNode.RequestType.IDENTIFY) + .triggerType(JourneySegmentTriggerNode.TriggerType.SEGMENT) + .type(JourneySegmentTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .eventId("x") + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofSend() { + val send = + JourneySendNode.builder() + .message( + JourneySendNode.Message.builder() + .template("x") + .data( + JourneySendNode.Message.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .delay( + JourneySendNode.Message.Delay.builder().until("x").timezone("x").build() + ) + .to( + JourneySendNode.Message.To.builder() + .emailOverride("x") + .phoneNumberOverride("x") + .userIdOverride("x") + .build() + ) + .build() + ) + .type(JourneySendNode.Type.SEND) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val journeyNode = JourneyNode.ofSend(send) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).contains(send) + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofSendRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofSend( + JourneySendNode.builder() + .message( + JourneySendNode.Message.builder() + .template("x") + .data( + JourneySendNode.Message.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .delay( + JourneySendNode.Message.Delay.builder() + .until("x") + .timezone("x") + .build() + ) + .to( + JourneySendNode.Message.To.builder() + .emailOverride("x") + .phoneNumberOverride("x") + .userIdOverride("x") + .build() + ) + .build() + ) + .type(JourneySendNode.Type.SEND) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofDelayDuration() { + val delayDuration = + JourneyDelayDurationNode.builder() + .duration("x") + .mode(JourneyDelayDurationNode.Mode.DURATION) + .type(JourneyDelayDurationNode.Type.DELAY) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val journeyNode = JourneyNode.ofDelayDuration(delayDuration) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).contains(delayDuration) + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofDelayDurationRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofDelayDuration( + JourneyDelayDurationNode.builder() + .duration("x") + .mode(JourneyDelayDurationNode.Mode.DURATION) + .type(JourneyDelayDurationNode.Type.DELAY) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofDelayUntil() { + val delayUntil = + JourneyDelayUntilNode.builder() + .mode(JourneyDelayUntilNode.Mode.UNTIL) + .type(JourneyDelayUntilNode.Type.DELAY) + .until("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val journeyNode = JourneyNode.ofDelayUntil(delayUntil) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).contains(delayUntil) + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofDelayUntilRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofDelayUntil( + JourneyDelayUntilNode.builder() + .mode(JourneyDelayUntilNode.Mode.UNTIL) + .type(JourneyDelayUntilNode.Type.DELAY) + .until("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofFetchGetDelete() { + val fetchGetDelete = + JourneyFetchGetDeleteNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchGetDeleteNode.Method.GET) + .type(JourneyFetchGetDeleteNode.Type.FETCH) + .url("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchGetDeleteNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchGetDeleteNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchGetDeleteNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val journeyNode = JourneyNode.ofFetchGetDelete(fetchGetDelete) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).contains(fetchGetDelete) + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofFetchGetDeleteRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofFetchGetDelete( + JourneyFetchGetDeleteNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchGetDeleteNode.Method.GET) + .type(JourneyFetchGetDeleteNode.Type.FETCH) + .url("x") + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchGetDeleteNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchGetDeleteNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchGetDeleteNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofFetchPostPut() { + val fetchPostPut = + JourneyFetchPostPutNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchPostPutNode.Method.POST) + .type(JourneyFetchPostPutNode.Type.FETCH) + .url("x") + .id("x") + .body("body") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchPostPutNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchPostPutNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchPostPutNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + + val journeyNode = JourneyNode.ofFetchPostPut(fetchPostPut) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).contains(fetchPostPut) + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofFetchPostPutRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofFetchPostPut( + JourneyFetchPostPutNode.builder() + .mergeStrategy(JourneyMergeStrategy.OVERWRITE) + .method(JourneyFetchPostPutNode.Method.POST) + .type(JourneyFetchPostPutNode.Type.FETCH) + .url("x") + .id("x") + .body("body") + .conditionsOfConditionAtom(listOf("string", "string")) + .headers( + JourneyFetchPostPutNode.Headers.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .queryParams( + JourneyFetchPostPutNode.QueryParams.builder() + .putAdditionalProperty("foo", JsonValue.from("string")) + .build() + ) + .responseSchema( + JourneyFetchPostPutNode.ResponseSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofAi() { + val ai = + JourneyAiNode.builder() + .outputSchema( + JourneyAiNode.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .type(JourneyAiNode.Type.AI) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .model("x") + .userPrompt("user_prompt") + .webSearch(true) + .build() + + val journeyNode = JourneyNode.ofAi(ai) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).contains(ai) + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofAiRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofAi( + JourneyAiNode.builder() + .outputSchema( + JourneyAiNode.OutputSchema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .type(JourneyAiNode.Type.AI) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .model("x") + .userPrompt("user_prompt") + .webSearch(true) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofThrottleStatic() { + val throttleStatic = + JourneyThrottleStaticNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleStaticNode.Scope.USER) + .type(JourneyThrottleStaticNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val journeyNode = JourneyNode.ofThrottleStatic(throttleStatic) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).contains(throttleStatic) + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofThrottleStaticRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofThrottleStatic( + JourneyThrottleStaticNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleStaticNode.Scope.USER) + .type(JourneyThrottleStaticNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofThrottleDynamic() { + val throttleDynamic = + JourneyThrottleDynamicNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleDynamicNode.Scope.DYNAMIC) + .throttleKey("x") + .type(JourneyThrottleDynamicNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val journeyNode = JourneyNode.ofThrottleDynamic(throttleDynamic) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).contains(throttleDynamic) + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofThrottleDynamicRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofThrottleDynamic( + JourneyThrottleDynamicNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleDynamicNode.Scope.DYNAMIC) + .throttleKey("x") + .type(JourneyThrottleDynamicNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofExit() { + val exit = JourneyExitNode.builder().type(JourneyExitNode.Type.EXIT).id("x").build() + + val journeyNode = JourneyNode.ofExit(exit) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).contains(exit) + assertThat(journeyNode.branch()).isEmpty + } + + @Test + fun ofExitRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofExit( + JourneyExitNode.builder().type(JourneyExitNode.Type.EXIT).id("x").build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + @Test + fun ofBranch() { + val branch = + JourneyNode.JourneyBranchNode.builder() + .default_( + JourneyNode.JourneyBranchNode.Default.builder() + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .label("x") + .build() + ) + .addPath( + JourneyNode.JourneyBranchNode.Path.builder() + .conditionsOfConditionAtom(listOf("string", "string")) + .nodes(listOf()) + .label("x") + .build() + ) + .type(JourneyNode.JourneyBranchNode.Type.BRANCH) + .id("x") + .build() + + val journeyNode = JourneyNode.ofBranch(branch) + + assertThat(journeyNode.apiInvokeTrigger()).isEmpty + assertThat(journeyNode.segmentTrigger()).isEmpty + assertThat(journeyNode.send()).isEmpty + assertThat(journeyNode.delayDuration()).isEmpty + assertThat(journeyNode.delayUntil()).isEmpty + assertThat(journeyNode.fetchGetDelete()).isEmpty + assertThat(journeyNode.fetchPostPut()).isEmpty + assertThat(journeyNode.ai()).isEmpty + assertThat(journeyNode.throttleStatic()).isEmpty + assertThat(journeyNode.throttleDynamic()).isEmpty + assertThat(journeyNode.exit()).isEmpty + assertThat(journeyNode.branch()).contains(branch) + } + + @Test + fun ofBranchRoundtrip() { + val jsonMapper = jsonMapper() + val journeyNode = + JourneyNode.ofBranch( + JourneyNode.JourneyBranchNode.builder() + .default_( + JourneyNode.JourneyBranchNode.Default.builder() + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .label("x") + .build() + ) + .addPath( + JourneyNode.JourneyBranchNode.Path.builder() + .conditionsOfConditionAtom(listOf("string", "string")) + .nodes(listOf()) + .label("x") + .build() + ) + .type(JourneyNode.JourneyBranchNode.Type.BRANCH) + .id("x") + .build() + ) + + val roundtrippedJourneyNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyNode).isEqualTo(journeyNode) + } + + 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 journeyNode = jsonMapper().convertValue(testCase.value, jacksonTypeRef()) + + val e = assertThrows { journeyNode.validate() } + assertThat(e).hasMessageStartingWith("Unknown ") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishParamsTest.kt new file mode 100644 index 00000000..722aef4e --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishParamsTest.kt @@ -0,0 +1,49 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyPublishParamsTest { + + @Test + fun create() { + JourneyPublishParams.builder() + .templateId("x") + .journeyPublishRequest(JourneyPublishRequest.builder().version("v321669910225").build()) + .build() + } + + @Test + fun pathParams() { + val params = JourneyPublishParams.builder().templateId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + JourneyPublishParams.builder() + .templateId("x") + .journeyPublishRequest( + JourneyPublishRequest.builder().version("v321669910225").build() + ) + .build() + + val body = params._body().getOrNull() + + assertThat(body).isEqualTo(JourneyPublishRequest.builder().version("v321669910225").build()) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = JourneyPublishParams.builder().templateId("x").build() + + val body = params._body().getOrNull() + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishRequestTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishRequestTest.kt new file mode 100644 index 00000000..0805d85f --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyPublishRequestTest.kt @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyPublishRequestTest { + + @Test + fun create() { + val journeyPublishRequest = JourneyPublishRequest.builder().version("v321669910225").build() + + assertThat(journeyPublishRequest.version()).contains("v321669910225") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyPublishRequest = JourneyPublishRequest.builder().version("v321669910225").build() + + val roundtrippedJourneyPublishRequest = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyPublishRequest), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyPublishRequest).isEqualTo(journeyPublishRequest) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyReplaceParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyReplaceParamsTest.kt new file mode 100644 index 00000000..8d7feb34 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyReplaceParamsTest.kt @@ -0,0 +1,146 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyReplaceParamsTest { + + @Test + fun create() { + JourneyReplaceParams.builder() + .templateId("x") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + .build() + } + + @Test + fun pathParams() { + val params = + JourneyReplaceParams.builder() + .templateId("x") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .build() + ) + .build() + + assertThat(params._pathParam(0)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + JourneyReplaceParams.builder() + .templateId("x") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + JourneyReplaceParams.builder() + .templateId("x") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .build() + ) + .build() + ) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyResponseTest.kt new file mode 100644 index 00000000..1e9d099d --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyResponseTest.kt @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyResponseTest { + + @Test + fun create() { + val journeyResponse = + JourneyResponse.builder() + .id("id") + .created(0L) + .creator("creator") + .enabled(true) + .name("name") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .published(0L) + .state(JourneyState.DRAFT) + .updated(0L) + .updater("updater") + .build() + + assertThat(journeyResponse.id()).isEqualTo("id") + assertThat(journeyResponse.created()).contains(0L) + assertThat(journeyResponse.creator()).contains("creator") + assertThat(journeyResponse.enabled()).isEqualTo(true) + assertThat(journeyResponse.name()).isEqualTo("name") + assertThat(journeyResponse.nodes()) + .containsExactly( + JourneyNode.ofApiInvokeTrigger( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + ) + assertThat(journeyResponse.published()).contains(0L) + assertThat(journeyResponse.state()).isEqualTo(JourneyState.DRAFT) + assertThat(journeyResponse.updated()).contains(0L) + assertThat(journeyResponse.updater()).contains("updater") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyResponse = + JourneyResponse.builder() + .id("id") + .created(0L) + .creator("creator") + .enabled(true) + .name("name") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .published(0L) + .state(JourneyState.DRAFT) + .updated(0L) + .updater("updater") + .build() + + val roundtrippedJourneyResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyResponse).isEqualTo(journeyResponse) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyRetrieveParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyRetrieveParamsTest.kt new file mode 100644 index 00000000..5a3ea5a0 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyRetrieveParamsTest.kt @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyRetrieveParamsTest { + + @Test + fun create() { + JourneyRetrieveParams.builder().templateId("x").version("published").build() + } + + @Test + fun pathParams() { + val params = JourneyRetrieveParams.builder().templateId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = JourneyRetrieveParams.builder().templateId("x").version("published").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().put("version", "published").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = JourneyRetrieveParams.builder().templateId("x").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneySegmentTriggerNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneySegmentTriggerNodeTest.kt new file mode 100644 index 00000000..af945f39 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneySegmentTriggerNodeTest.kt @@ -0,0 +1,57 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneySegmentTriggerNodeTest { + + @Test + fun create() { + val journeySegmentTriggerNode = + JourneySegmentTriggerNode.builder() + .requestType(JourneySegmentTriggerNode.RequestType.IDENTIFY) + .triggerType(JourneySegmentTriggerNode.TriggerType.SEGMENT) + .type(JourneySegmentTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .eventId("x") + .build() + + assertThat(journeySegmentTriggerNode.requestType()) + .isEqualTo(JourneySegmentTriggerNode.RequestType.IDENTIFY) + assertThat(journeySegmentTriggerNode.triggerType()) + .isEqualTo(JourneySegmentTriggerNode.TriggerType.SEGMENT) + assertThat(journeySegmentTriggerNode.type()) + .isEqualTo(JourneySegmentTriggerNode.Type.TRIGGER) + assertThat(journeySegmentTriggerNode.id()).contains("x") + assertThat(journeySegmentTriggerNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + assertThat(journeySegmentTriggerNode.eventId()).contains("x") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeySegmentTriggerNode = + JourneySegmentTriggerNode.builder() + .requestType(JourneySegmentTriggerNode.RequestType.IDENTIFY) + .triggerType(JourneySegmentTriggerNode.TriggerType.SEGMENT) + .type(JourneySegmentTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .eventId("x") + .build() + + val roundtrippedJourneySegmentTriggerNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeySegmentTriggerNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneySegmentTriggerNode).isEqualTo(journeySegmentTriggerNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneySendNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneySendNodeTest.kt new file mode 100644 index 00000000..f8b6e72e --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneySendNodeTest.kt @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.JsonValue +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneySendNodeTest { + + @Test + fun create() { + val journeySendNode = + JourneySendNode.builder() + .message( + JourneySendNode.Message.builder() + .template("x") + .data( + JourneySendNode.Message.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .delay( + JourneySendNode.Message.Delay.builder().until("x").timezone("x").build() + ) + .to( + JourneySendNode.Message.To.builder() + .emailOverride("x") + .phoneNumberOverride("x") + .userIdOverride("x") + .build() + ) + .build() + ) + .type(JourneySendNode.Type.SEND) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + assertThat(journeySendNode.message()) + .isEqualTo( + JourneySendNode.Message.builder() + .template("x") + .data( + JourneySendNode.Message.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .delay(JourneySendNode.Message.Delay.builder().until("x").timezone("x").build()) + .to( + JourneySendNode.Message.To.builder() + .emailOverride("x") + .phoneNumberOverride("x") + .userIdOverride("x") + .build() + ) + .build() + ) + assertThat(journeySendNode.type()).isEqualTo(JourneySendNode.Type.SEND) + assertThat(journeySendNode.id()).contains("x") + assertThat(journeySendNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeySendNode = + JourneySendNode.builder() + .message( + JourneySendNode.Message.builder() + .template("x") + .data( + JourneySendNode.Message.Data.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .delay( + JourneySendNode.Message.Delay.builder().until("x").timezone("x").build() + ) + .to( + JourneySendNode.Message.To.builder() + .emailOverride("x") + .phoneNumberOverride("x") + .userIdOverride("x") + .build() + ) + .build() + ) + .type(JourneySendNode.Type.SEND) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val roundtrippedJourneySendNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeySendNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneySendNode).isEqualTo(journeySendNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateCreateRequestTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateCreateRequestTest.kt new file mode 100644 index 00000000..82c1780c --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateCreateRequestTest.kt @@ -0,0 +1,150 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.courier.models.ElementalTextNodeWithType +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyTemplateCreateRequestTest { + + @Test + fun create() { + val journeyTemplateCreateRequest = + JourneyTemplateCreateRequest.builder() + .channel("x") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content.Scope.DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + + assertThat(journeyTemplateCreateRequest.channel()).isEqualTo("x") + assertThat(journeyTemplateCreateRequest.notification()) + .isEqualTo( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder().id("id").build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope(JourneyTemplateCreateRequest.Notification.Content.Scope.DEFAULT) + .build() + ) + .name("name") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + assertThat(journeyTemplateCreateRequest.providerKey()).contains("x") + assertThat(journeyTemplateCreateRequest.state()).contains("state") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyTemplateCreateRequest = + JourneyTemplateCreateRequest.builder() + .channel("x") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content.Scope.DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + + val roundtrippedJourneyTemplateCreateRequest = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyTemplateCreateRequest), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyTemplateCreateRequest).isEqualTo(journeyTemplateCreateRequest) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateGetResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateGetResponseTest.kt new file mode 100644 index 00000000..ae690afa --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateGetResponseTest.kt @@ -0,0 +1,119 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.courier.models.ElementalTextNodeWithType +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyTemplateGetResponseTest { + + @Test + fun create() { + val journeyTemplateGetResponse = + JourneyTemplateGetResponse.builder() + .id("id") + .brand(JourneyTemplateGetResponse.Brand.builder().id("id").build()) + .content( + JourneyTemplateGetResponse.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version(JourneyTemplateGetResponse.Content.Version._2022_01_01) + .scope(JourneyTemplateGetResponse.Content.Scope.DEFAULT) + .build() + ) + .created(0L) + .creator("creator") + .name("name") + .state(JourneyTemplateGetResponse.State.DRAFT) + .subscription( + JourneyTemplateGetResponse.Subscription.builder().topicId("topic_id").build() + ) + .addTag("string") + .updated(0L) + .updater("updater") + .build() + + assertThat(journeyTemplateGetResponse.id()).isEqualTo("id") + assertThat(journeyTemplateGetResponse.brand()) + .contains(JourneyTemplateGetResponse.Brand.builder().id("id").build()) + assertThat(journeyTemplateGetResponse.content()) + .isEqualTo( + JourneyTemplateGetResponse.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version(JourneyTemplateGetResponse.Content.Version._2022_01_01) + .scope(JourneyTemplateGetResponse.Content.Scope.DEFAULT) + .build() + ) + assertThat(journeyTemplateGetResponse.created()).isEqualTo(0L) + assertThat(journeyTemplateGetResponse.creator()).isEqualTo("creator") + assertThat(journeyTemplateGetResponse.name()).isEqualTo("name") + assertThat(journeyTemplateGetResponse.state()) + .isEqualTo(JourneyTemplateGetResponse.State.DRAFT) + assertThat(journeyTemplateGetResponse.subscription()) + .contains(JourneyTemplateGetResponse.Subscription.builder().topicId("topic_id").build()) + assertThat(journeyTemplateGetResponse.tags()).containsExactly("string") + assertThat(journeyTemplateGetResponse.updated()).contains(0L) + assertThat(journeyTemplateGetResponse.updater()).contains("updater") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyTemplateGetResponse = + JourneyTemplateGetResponse.builder() + .id("id") + .brand(JourneyTemplateGetResponse.Brand.builder().id("id").build()) + .content( + JourneyTemplateGetResponse.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version(JourneyTemplateGetResponse.Content.Version._2022_01_01) + .scope(JourneyTemplateGetResponse.Content.Scope.DEFAULT) + .build() + ) + .created(0L) + .creator("creator") + .name("name") + .state(JourneyTemplateGetResponse.State.DRAFT) + .subscription( + JourneyTemplateGetResponse.Subscription.builder().topicId("topic_id").build() + ) + .addTag("string") + .updated(0L) + .updater("updater") + .build() + + val roundtrippedJourneyTemplateGetResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyTemplateGetResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyTemplateGetResponse).isEqualTo(journeyTemplateGetResponse) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateListResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateListResponseTest.kt new file mode 100644 index 00000000..0ea6c8e4 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateListResponseTest.kt @@ -0,0 +1,77 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.courier.models.Paging +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyTemplateListResponseTest { + + @Test + fun create() { + val journeyTemplateListResponse = + JourneyTemplateListResponse.builder() + .paging(Paging.builder().more(true).cursor("cursor").build()) + .addResult( + JourneyTemplateSummary.builder() + .id("id") + .created(0L) + .creator("creator") + .name("name") + .state("state") + .addTag("string") + .updated(0L) + .updater("updater") + .build() + ) + .build() + + assertThat(journeyTemplateListResponse.paging()) + .isEqualTo(Paging.builder().more(true).cursor("cursor").build()) + assertThat(journeyTemplateListResponse.results()) + .containsExactly( + JourneyTemplateSummary.builder() + .id("id") + .created(0L) + .creator("creator") + .name("name") + .state("state") + .addTag("string") + .updated(0L) + .updater("updater") + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyTemplateListResponse = + JourneyTemplateListResponse.builder() + .paging(Paging.builder().more(true).cursor("cursor").build()) + .addResult( + JourneyTemplateSummary.builder() + .id("id") + .created(0L) + .creator("creator") + .name("name") + .state("state") + .addTag("string") + .updated(0L) + .updater("updater") + .build() + ) + .build() + + val roundtrippedJourneyTemplateListResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyTemplateListResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyTemplateListResponse).isEqualTo(journeyTemplateListResponse) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplatePublishRequestTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplatePublishRequestTest.kt new file mode 100644 index 00000000..c73a25e8 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplatePublishRequestTest.kt @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyTemplatePublishRequestTest { + + @Test + fun create() { + val journeyTemplatePublishRequest = + JourneyTemplatePublishRequest.builder().version("v321669910225").build() + + assertThat(journeyTemplatePublishRequest.version()).contains("v321669910225") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyTemplatePublishRequest = + JourneyTemplatePublishRequest.builder().version("v321669910225").build() + + val roundtrippedJourneyTemplatePublishRequest = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyTemplatePublishRequest), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyTemplatePublishRequest) + .isEqualTo(journeyTemplatePublishRequest) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateReplaceRequestTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateReplaceRequestTest.kt new file mode 100644 index 00000000..c6cd83cf --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateReplaceRequestTest.kt @@ -0,0 +1,145 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.courier.models.ElementalTextNodeWithType +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyTemplateReplaceRequestTest { + + @Test + fun create() { + val journeyTemplateReplaceRequest = + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateReplaceRequest.Notification.Content.Scope.DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .state("state") + .build() + + assertThat(journeyTemplateReplaceRequest.notification()) + .isEqualTo( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder().id("id").build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope(JourneyTemplateReplaceRequest.Notification.Content.Scope.DEFAULT) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + assertThat(journeyTemplateReplaceRequest.state()).contains("state") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyTemplateReplaceRequest = + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateReplaceRequest.Notification.Content.Scope.DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .state("state") + .build() + + val roundtrippedJourneyTemplateReplaceRequest = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyTemplateReplaceRequest), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyTemplateReplaceRequest) + .isEqualTo(journeyTemplateReplaceRequest) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateSummaryTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateSummaryTest.kt new file mode 100644 index 00000000..44095ced --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyTemplateSummaryTest.kt @@ -0,0 +1,59 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyTemplateSummaryTest { + + @Test + fun create() { + val journeyTemplateSummary = + JourneyTemplateSummary.builder() + .id("id") + .created(0L) + .creator("creator") + .name("name") + .state("state") + .addTag("string") + .updated(0L) + .updater("updater") + .build() + + assertThat(journeyTemplateSummary.id()).isEqualTo("id") + assertThat(journeyTemplateSummary.created()).isEqualTo(0L) + assertThat(journeyTemplateSummary.creator()).isEqualTo("creator") + assertThat(journeyTemplateSummary.name()).isEqualTo("name") + assertThat(journeyTemplateSummary.state()).isEqualTo("state") + assertThat(journeyTemplateSummary.tags()).containsExactly("string") + assertThat(journeyTemplateSummary.updated()).contains(0L) + assertThat(journeyTemplateSummary.updater()).contains("updater") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyTemplateSummary = + JourneyTemplateSummary.builder() + .id("id") + .created(0L) + .creator("creator") + .name("name") + .state("state") + .addTag("string") + .updated(0L) + .updater("updater") + .build() + + val roundtrippedJourneyTemplateSummary = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyTemplateSummary), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyTemplateSummary).isEqualTo(journeyTemplateSummary) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyThrottleDynamicNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyThrottleDynamicNodeTest.kt new file mode 100644 index 00000000..7b3e0f2f --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyThrottleDynamicNodeTest.kt @@ -0,0 +1,59 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyThrottleDynamicNodeTest { + + @Test + fun create() { + val journeyThrottleDynamicNode = + JourneyThrottleDynamicNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleDynamicNode.Scope.DYNAMIC) + .throttleKey("x") + .type(JourneyThrottleDynamicNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + assertThat(journeyThrottleDynamicNode.maxAllowed()).isEqualTo(1L) + assertThat(journeyThrottleDynamicNode.period()).isEqualTo("x") + assertThat(journeyThrottleDynamicNode.scope()) + .isEqualTo(JourneyThrottleDynamicNode.Scope.DYNAMIC) + assertThat(journeyThrottleDynamicNode.throttleKey()).isEqualTo("x") + assertThat(journeyThrottleDynamicNode.type()) + .isEqualTo(JourneyThrottleDynamicNode.Type.THROTTLE) + assertThat(journeyThrottleDynamicNode.id()).contains("x") + assertThat(journeyThrottleDynamicNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyThrottleDynamicNode = + JourneyThrottleDynamicNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleDynamicNode.Scope.DYNAMIC) + .throttleKey("x") + .type(JourneyThrottleDynamicNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val roundtrippedJourneyThrottleDynamicNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyThrottleDynamicNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyThrottleDynamicNode).isEqualTo(journeyThrottleDynamicNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyThrottleStaticNodeTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyThrottleStaticNodeTest.kt new file mode 100644 index 00000000..1cf8ed0e --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyThrottleStaticNodeTest.kt @@ -0,0 +1,56 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyThrottleStaticNodeTest { + + @Test + fun create() { + val journeyThrottleStaticNode = + JourneyThrottleStaticNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleStaticNode.Scope.USER) + .type(JourneyThrottleStaticNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + assertThat(journeyThrottleStaticNode.maxAllowed()).isEqualTo(1L) + assertThat(journeyThrottleStaticNode.period()).isEqualTo("x") + assertThat(journeyThrottleStaticNode.scope()) + .isEqualTo(JourneyThrottleStaticNode.Scope.USER) + assertThat(journeyThrottleStaticNode.type()) + .isEqualTo(JourneyThrottleStaticNode.Type.THROTTLE) + assertThat(journeyThrottleStaticNode.id()).contains("x") + assertThat(journeyThrottleStaticNode.conditions()) + .contains(JourneyConditionsField.ofConditionAtom(listOf("string", "string"))) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyThrottleStaticNode = + JourneyThrottleStaticNode.builder() + .maxAllowed(1L) + .period("x") + .scope(JourneyThrottleStaticNode.Scope.USER) + .type(JourneyThrottleStaticNode.Type.THROTTLE) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .build() + + val roundtrippedJourneyThrottleStaticNode = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyThrottleStaticNode), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyThrottleStaticNode).isEqualTo(journeyThrottleStaticNode) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyVersionItemTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyVersionItemTest.kt new file mode 100644 index 00000000..2bbe28db --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyVersionItemTest.kt @@ -0,0 +1,50 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyVersionItemTest { + + @Test + fun create() { + val journeyVersionItem = + JourneyVersionItem.builder() + .created(0L) + .creator("creator") + .name("name") + .published(0L) + .version("version") + .build() + + assertThat(journeyVersionItem.created()).contains(0L) + assertThat(journeyVersionItem.creator()).contains("creator") + assertThat(journeyVersionItem.name()).isEqualTo("name") + assertThat(journeyVersionItem.published()).contains(0L) + assertThat(journeyVersionItem.version()).isEqualTo("version") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyVersionItem = + JourneyVersionItem.builder() + .created(0L) + .creator("creator") + .name("name") + .published(0L) + .version("version") + .build() + + val roundtrippedJourneyVersionItem = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyVersionItem), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyVersionItem).isEqualTo(journeyVersionItem) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyVersionsListResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyVersionsListResponseTest.kt new file mode 100644 index 00000000..9b2d893a --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/JourneyVersionsListResponseTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys + +import com.courier.core.jsonMapper +import com.courier.models.Paging +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class JourneyVersionsListResponseTest { + + @Test + fun create() { + val journeyVersionsListResponse = + JourneyVersionsListResponse.builder() + .paging(Paging.builder().more(true).cursor("cursor").build()) + .addResult( + JourneyVersionItem.builder() + .created(0L) + .creator("creator") + .name("name") + .published(0L) + .version("version") + .build() + ) + .build() + + assertThat(journeyVersionsListResponse.paging()) + .isEqualTo(Paging.builder().more(true).cursor("cursor").build()) + assertThat(journeyVersionsListResponse.results()) + .containsExactly( + JourneyVersionItem.builder() + .created(0L) + .creator("creator") + .name("name") + .published(0L) + .version("version") + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val journeyVersionsListResponse = + JourneyVersionsListResponse.builder() + .paging(Paging.builder().more(true).cursor("cursor").build()) + .addResult( + JourneyVersionItem.builder() + .created(0L) + .creator("creator") + .name("name") + .published(0L) + .version("version") + .build() + ) + .build() + + val roundtrippedJourneyVersionsListResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(journeyVersionsListResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedJourneyVersionsListResponse).isEqualTo(journeyVersionsListResponse) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateArchiveParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateArchiveParamsTest.kt new file mode 100644 index 00000000..bc7ed529 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateArchiveParamsTest.kt @@ -0,0 +1,24 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplateArchiveParamsTest { + + @Test + fun create() { + TemplateArchiveParams.builder().templateId("x").notificationId("x").build() + } + + @Test + fun pathParams() { + val params = TemplateArchiveParams.builder().templateId("x").notificationId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + assertThat(params._pathParam(1)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateCreateParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateCreateParamsTest.kt new file mode 100644 index 00000000..cb39db3e --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateCreateParamsTest.kt @@ -0,0 +1,279 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.models.ElementalTextNodeWithType +import com.courier.models.journeys.JourneyTemplateCreateRequest +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplateCreateParamsTest { + + @Test + fun create() { + TemplateCreateParams.builder() + .templateId("x") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content.Scope + .DEFAULT + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + ) + .build() + } + + @Test + fun pathParams() { + val params = + TemplateCreateParams.builder() + .templateId("x") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version( + JourneyTemplateCreateRequest.Notification.Content + .Version + ._2022_01_01 + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .build() + ) + .build() + + assertThat(params._pathParam(0)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + TemplateCreateParams.builder() + .templateId("x") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content + .Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content.Scope + .DEFAULT + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content.Scope + .DEFAULT + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + TemplateCreateParams.builder() + .templateId("x") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version( + JourneyTemplateCreateRequest.Notification.Content + .Version + ._2022_01_01 + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version( + JourneyTemplateCreateRequest.Notification.Content.Version + ._2022_01_01 + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .build() + ) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateListParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateListParamsTest.kt new file mode 100644 index 00000000..e1162702 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateListParamsTest.kt @@ -0,0 +1,43 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplateListParamsTest { + + @Test + fun create() { + TemplateListParams.builder().templateId("x").cursor("cursor").limit(1L).build() + } + + @Test + fun pathParams() { + val params = TemplateListParams.builder().templateId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = TemplateListParams.builder().templateId("x").cursor("cursor").limit(1L).build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo(QueryParams.builder().put("cursor", "cursor").put("limit", "1").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = TemplateListParams.builder().templateId("x").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParamsTest.kt new file mode 100644 index 00000000..0f819608 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateListVersionsParamsTest.kt @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplateListVersionsParamsTest { + + @Test + fun create() { + TemplateListVersionsParams.builder().templateId("x").notificationId("x").build() + } + + @Test + fun pathParams() { + val params = + TemplateListVersionsParams.builder().templateId("x").notificationId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + assertThat(params._pathParam(1)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplatePublishParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplatePublishParamsTest.kt new file mode 100644 index 00000000..b7917c8c --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplatePublishParamsTest.kt @@ -0,0 +1,56 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.models.journeys.JourneyTemplatePublishRequest +import kotlin.jvm.optionals.getOrNull +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplatePublishParamsTest { + + @Test + fun create() { + TemplatePublishParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplatePublishRequest( + JourneyTemplatePublishRequest.builder().version("v321669910225").build() + ) + .build() + } + + @Test + fun pathParams() { + val params = TemplatePublishParams.builder().templateId("x").notificationId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + assertThat(params._pathParam(1)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } + + @Test + fun body() { + val params = + TemplatePublishParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplatePublishRequest( + JourneyTemplatePublishRequest.builder().version("v321669910225").build() + ) + .build() + + val body = params._body().getOrNull() + + assertThat(body) + .isEqualTo(JourneyTemplatePublishRequest.builder().version("v321669910225").build()) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = TemplatePublishParams.builder().templateId("x").notificationId("x").build() + + val body = params._body().getOrNull() + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateReplaceParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateReplaceParamsTest.kt new file mode 100644 index 00000000..eafb6383 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateReplaceParamsTest.kt @@ -0,0 +1,278 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import com.courier.models.ElementalTextNodeWithType +import com.courier.models.journeys.JourneyTemplateReplaceRequest +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplateReplaceParamsTest { + + @Test + fun create() { + TemplateReplaceParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplateReplaceRequest( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateReplaceRequest.Notification.Content.Scope + .DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .state("state") + .build() + ) + .build() + } + + @Test + fun pathParams() { + val params = + TemplateReplaceParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplateReplaceRequest( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version( + JourneyTemplateReplaceRequest.Notification.Content + .Version + ._2022_01_01 + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription + .builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .build() + ) + .build() + + assertThat(params._pathParam(0)).isEqualTo("x") + assertThat(params._pathParam(1)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } + + @Test + fun body() { + val params = + TemplateReplaceParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplateReplaceRequest( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content + .Version + ._2022_01_01 + ) + .scope( + JourneyTemplateReplaceRequest.Notification.Content.Scope + .DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription + .builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .state("state") + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content.Version + ._2022_01_01 + ) + .scope( + JourneyTemplateReplaceRequest.Notification.Content.Scope + .DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .state("state") + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + TemplateReplaceParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplateReplaceRequest( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version( + JourneyTemplateReplaceRequest.Notification.Content + .Version + ._2022_01_01 + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription + .builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement(ElementalTextNodeWithType.builder().build()) + .version( + JourneyTemplateReplaceRequest.Notification.Content.Version + ._2022_01_01 + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription.builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .build() + ) + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParamsTest.kt new file mode 100644 index 00000000..2c3f5fcb --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/journeys/templates/TemplateRetrieveParamsTest.kt @@ -0,0 +1,24 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.journeys.templates + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplateRetrieveParamsTest { + + @Test + fun create() { + TemplateRetrieveParams.builder().templateId("x").notificationId("x").build() + } + + @Test + fun pathParams() { + val params = TemplateRetrieveParams.builder().templateId("x").notificationId("x").build() + + assertThat(params._pathParam(0)).isEqualTo("x") + assertThat(params._pathParam(1)).isEqualTo("x") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageResponseTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageResponseTest.kt index 24383b13..9cfd6f66 100644 --- a/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageResponseTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/models/send/SendMessageResponseTest.kt @@ -12,16 +12,16 @@ internal class SendMessageResponseTest { @Test fun create() { val sendMessageResponse = - SendMessageResponse.builder().requestId("1-65f240a0-47a6a120c8374de9bcf9f22c").build() + SendMessageResponse.builder().requestId("1-69f561d3-7ad9d453fb6a7012efc2c5ad").build() - assertThat(sendMessageResponse.requestId()).isEqualTo("1-65f240a0-47a6a120c8374de9bcf9f22c") + assertThat(sendMessageResponse.requestId()).isEqualTo("1-69f561d3-7ad9d453fb6a7012efc2c5ad") } @Test fun roundtrip() { val jsonMapper = jsonMapper() val sendMessageResponse = - SendMessageResponse.builder().requestId("1-65f240a0-47a6a120c8374de9bcf9f22c").build() + SendMessageResponse.builder().requestId("1-69f561d3-7ad9d453fb6a7012efc2c5ad").build() val roundtrippedSendMessageResponse = jsonMapper.readValue( diff --git a/courier-java-core/src/test/kotlin/com/courier/models/tenants/templates/TemplateDeleteParamsTest.kt b/courier-java-core/src/test/kotlin/com/courier/models/tenants/templates/TemplateDeleteParamsTest.kt new file mode 100644 index 00000000..45b27255 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/models/tenants/templates/TemplateDeleteParamsTest.kt @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.models.tenants.templates + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class TemplateDeleteParamsTest { + + @Test + fun create() { + TemplateDeleteParams.builder().tenantId("tenant_id").templateId("template_id").build() + } + + @Test + fun pathParams() { + val params = + TemplateDeleteParams.builder().tenantId("tenant_id").templateId("template_id").build() + + assertThat(params._pathParam(0)).isEqualTo("tenant_id") + assertThat(params._pathParam(1)).isEqualTo("template_id") + // out-of-bound path param + assertThat(params._pathParam(2)).isEqualTo("") + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt index ec4377a8..00da17a7 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/JourneyServiceAsyncTest.kt @@ -4,14 +4,81 @@ package com.courier.services.async import com.courier.client.okhttp.CourierOkHttpClientAsync import com.courier.core.JsonValue +import com.courier.models.journeys.CreateJourneyRequest +import com.courier.models.journeys.JourneyApiInvokeTriggerNode import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams +import com.courier.models.journeys.JourneyPublishParams +import com.courier.models.journeys.JourneyPublishRequest +import com.courier.models.journeys.JourneyReplaceParams +import com.courier.models.journeys.JourneyRetrieveParams +import com.courier.models.journeys.JourneyState import com.courier.models.journeys.JourneysInvokeRequest import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test internal class JourneyServiceAsyncTest { + @Disabled("Mock server tests are disabled") + @Test + fun create() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val journeyServiceAsync = client.journeys() + + val journeyResponseFuture = + journeyServiceAsync.create( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + + val journeyResponse = journeyResponseFuture.get() + journeyResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun retrieve() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val journeyServiceAsync = client.journeys() + + val journeyResponseFuture = + journeyServiceAsync.retrieve( + JourneyRetrieveParams.builder().templateId("x").version("published").build() + ) + + val journeyResponse = journeyResponseFuture.get() + journeyResponse.validate() + } + @Disabled("Mock server tests are disabled") @Test fun list() { @@ -30,6 +97,17 @@ internal class JourneyServiceAsyncTest { journeysListResponse.validate() } + @Disabled("Mock server tests are disabled") + @Test + fun archive() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val journeyServiceAsync = client.journeys() + + val future = journeyServiceAsync.archive("x") + + val response = future.get() + } + @Disabled("Mock server tests are disabled") @Test fun invoke() { @@ -62,4 +140,73 @@ internal class JourneyServiceAsyncTest { val journeysInvokeResponse = journeysInvokeResponseFuture.get() journeysInvokeResponse.validate() } + + @Disabled("Mock server tests are disabled") + @Test + fun listVersions() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val journeyServiceAsync = client.journeys() + + val journeyVersionsListResponseFuture = journeyServiceAsync.listVersions("x") + + val journeyVersionsListResponse = journeyVersionsListResponseFuture.get() + journeyVersionsListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun publish() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val journeyServiceAsync = client.journeys() + + val journeyResponseFuture = + journeyServiceAsync.publish( + JourneyPublishParams.builder() + .templateId("x") + .journeyPublishRequest( + JourneyPublishRequest.builder().version("v321669910225").build() + ) + .build() + ) + + val journeyResponse = journeyResponseFuture.get() + journeyResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun replace() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val journeyServiceAsync = client.journeys() + + val journeyResponseFuture = + journeyServiceAsync.replace( + JourneyReplaceParams.builder() + .templateId("x") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + .build() + ) + + val journeyResponse = journeyResponseFuture.get() + journeyResponse.validate() + } } diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncTest.kt new file mode 100644 index 00000000..dd968116 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/journeys/TemplateServiceAsyncTest.kt @@ -0,0 +1,228 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.async.journeys + +import com.courier.client.okhttp.CourierOkHttpClientAsync +import com.courier.models.ElementalTextNodeWithType +import com.courier.models.journeys.JourneyTemplateCreateRequest +import com.courier.models.journeys.JourneyTemplatePublishRequest +import com.courier.models.journeys.JourneyTemplateReplaceRequest +import com.courier.models.journeys.templates.TemplateArchiveParams +import com.courier.models.journeys.templates.TemplateCreateParams +import com.courier.models.journeys.templates.TemplateListParams +import com.courier.models.journeys.templates.TemplateListVersionsParams +import com.courier.models.journeys.templates.TemplatePublishParams +import com.courier.models.journeys.templates.TemplateReplaceParams +import com.courier.models.journeys.templates.TemplateRetrieveParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test + +internal class TemplateServiceAsyncTest { + + @Disabled("Mock server tests are disabled") + @Test + fun create() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.journeys().templates() + + val journeyTemplateGetResponseFuture = + templateServiceAsync.create( + TemplateCreateParams.builder() + .templateId("x") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content + .Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content + .Scope + .DEFAULT + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription + .builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + ) + .build() + ) + + val journeyTemplateGetResponse = journeyTemplateGetResponseFuture.get() + journeyTemplateGetResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun retrieve() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.journeys().templates() + + val journeyTemplateGetResponseFuture = + templateServiceAsync.retrieve( + TemplateRetrieveParams.builder().templateId("x").notificationId("x").build() + ) + + val journeyTemplateGetResponse = journeyTemplateGetResponseFuture.get() + journeyTemplateGetResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun list() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.journeys().templates() + + val journeyTemplateListResponseFuture = + templateServiceAsync.list( + TemplateListParams.builder().templateId("x").cursor("cursor").limit(1L).build() + ) + + val journeyTemplateListResponse = journeyTemplateListResponseFuture.get() + journeyTemplateListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun archive() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.journeys().templates() + + val future = + templateServiceAsync.archive( + TemplateArchiveParams.builder().templateId("x").notificationId("x").build() + ) + + val response = future.get() + } + + @Disabled("Mock server tests are disabled") + @Test + fun listVersions() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.journeys().templates() + + val notificationTemplateVersionListResponseFuture = + templateServiceAsync.listVersions( + TemplateListVersionsParams.builder().templateId("x").notificationId("x").build() + ) + + val notificationTemplateVersionListResponse = + notificationTemplateVersionListResponseFuture.get() + notificationTemplateVersionListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun publish() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.journeys().templates() + + val future = + templateServiceAsync.publish( + TemplatePublishParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplatePublishRequest( + JourneyTemplatePublishRequest.builder().version("v321669910225").build() + ) + .build() + ) + + val response = future.get() + } + + @Disabled("Mock server tests are disabled") + @Test + fun replace() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.journeys().templates() + + val journeyTemplateGetResponseFuture = + templateServiceAsync.replace( + TemplateReplaceParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplateReplaceRequest( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content + .Version + ._2022_01_01 + ) + .scope( + JourneyTemplateReplaceRequest.Notification.Content + .Scope + .DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription + .builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .state("state") + .build() + ) + .build() + ) + + val journeyTemplateGetResponse = journeyTemplateGetResponseFuture.get() + journeyTemplateGetResponse.validate() + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncTest.kt index 02337e31..164b2949 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/async/tenants/TemplateServiceAsyncTest.kt @@ -12,6 +12,7 @@ import com.courier.models.MessageRouting import com.courier.models.tenants.PostTenantTemplatePublishRequest import com.courier.models.tenants.PutTenantTemplateRequest import com.courier.models.tenants.TenantTemplateInput +import com.courier.models.tenants.templates.TemplateDeleteParams import com.courier.models.tenants.templates.TemplateListParams import com.courier.models.tenants.templates.TemplatePublishParams import com.courier.models.tenants.templates.TemplateReplaceParams @@ -58,6 +59,23 @@ internal class TemplateServiceAsyncTest { templates.validate() } + @Disabled("Mock server tests are disabled") + @Test + fun delete() { + val client = CourierOkHttpClientAsync.builder().apiKey("My API Key").build() + val templateServiceAsync = client.tenants().templates() + + val future = + templateServiceAsync.delete( + TemplateDeleteParams.builder() + .tenantId("tenant_id") + .templateId("template_id") + .build() + ) + + val response = future.get() + } + @Disabled("Mock server tests are disabled") @Test fun publish() { diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt index 2422b226..5e946adf 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/JourneyServiceTest.kt @@ -4,14 +4,79 @@ package com.courier.services.blocking import com.courier.client.okhttp.CourierOkHttpClient import com.courier.core.JsonValue +import com.courier.models.journeys.CreateJourneyRequest +import com.courier.models.journeys.JourneyApiInvokeTriggerNode import com.courier.models.journeys.JourneyInvokeParams import com.courier.models.journeys.JourneyListParams +import com.courier.models.journeys.JourneyPublishParams +import com.courier.models.journeys.JourneyPublishRequest +import com.courier.models.journeys.JourneyReplaceParams +import com.courier.models.journeys.JourneyRetrieveParams +import com.courier.models.journeys.JourneyState import com.courier.models.journeys.JourneysInvokeRequest import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test internal class JourneyServiceTest { + @Disabled("Mock server tests are disabled") + @Test + fun create() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val journeyService = client.journeys() + + val journeyResponse = + journeyService.create( + CreateJourneyRequest.builder() + .name("Welcome Journey") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("trigger-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("send-1") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + + journeyResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun retrieve() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val journeyService = client.journeys() + + val journeyResponse = + journeyService.retrieve( + JourneyRetrieveParams.builder().templateId("x").version("published").build() + ) + + journeyResponse.validate() + } + @Disabled("Mock server tests are disabled") @Test fun list() { @@ -29,6 +94,15 @@ internal class JourneyServiceTest { journeysListResponse.validate() } + @Disabled("Mock server tests are disabled") + @Test + fun archive() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val journeyService = client.journeys() + + journeyService.archive("x") + } + @Disabled("Mock server tests are disabled") @Test fun invoke() { @@ -60,4 +134,70 @@ internal class JourneyServiceTest { journeysInvokeResponse.validate() } + + @Disabled("Mock server tests are disabled") + @Test + fun listVersions() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val journeyService = client.journeys() + + val journeyVersionsListResponse = journeyService.listVersions("x") + + journeyVersionsListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun publish() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val journeyService = client.journeys() + + val journeyResponse = + journeyService.publish( + JourneyPublishParams.builder() + .templateId("x") + .journeyPublishRequest( + JourneyPublishRequest.builder().version("v321669910225").build() + ) + .build() + ) + + journeyResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun replace() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val journeyService = client.journeys() + + val journeyResponse = + journeyService.replace( + JourneyReplaceParams.builder() + .templateId("x") + .createJourneyRequest( + CreateJourneyRequest.builder() + .name("Welcome Journey v2") + .addNode( + JourneyApiInvokeTriggerNode.builder() + .triggerType(JourneyApiInvokeTriggerNode.TriggerType.API_INVOKE) + .type(JourneyApiInvokeTriggerNode.Type.TRIGGER) + .id("x") + .conditionsOfConditionAtom(listOf("string", "string")) + .schema( + JourneyApiInvokeTriggerNode.Schema.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .build() + ) + .enabled(true) + .state(JourneyState.DRAFT) + .build() + ) + .build() + ) + + journeyResponse.validate() + } } diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/journeys/TemplateServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/journeys/TemplateServiceTest.kt new file mode 100644 index 00000000..736a1675 --- /dev/null +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/journeys/TemplateServiceTest.kt @@ -0,0 +1,216 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.courier.services.blocking.journeys + +import com.courier.client.okhttp.CourierOkHttpClient +import com.courier.models.ElementalTextNodeWithType +import com.courier.models.journeys.JourneyTemplateCreateRequest +import com.courier.models.journeys.JourneyTemplatePublishRequest +import com.courier.models.journeys.JourneyTemplateReplaceRequest +import com.courier.models.journeys.templates.TemplateArchiveParams +import com.courier.models.journeys.templates.TemplateCreateParams +import com.courier.models.journeys.templates.TemplateListParams +import com.courier.models.journeys.templates.TemplateListVersionsParams +import com.courier.models.journeys.templates.TemplatePublishParams +import com.courier.models.journeys.templates.TemplateReplaceParams +import com.courier.models.journeys.templates.TemplateRetrieveParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test + +internal class TemplateServiceTest { + + @Disabled("Mock server tests are disabled") + @Test + fun create() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.journeys().templates() + + val journeyTemplateGetResponse = + templateService.create( + TemplateCreateParams.builder() + .templateId("x") + .journeyTemplateCreateRequest( + JourneyTemplateCreateRequest.builder() + .channel("email") + .notification( + JourneyTemplateCreateRequest.Notification.builder() + .brand( + JourneyTemplateCreateRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateCreateRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateCreateRequest.Notification.Content + .Version + ._2022_01_01 + ) + .scope( + JourneyTemplateCreateRequest.Notification.Content + .Scope + .DEFAULT + ) + .build() + ) + .name("Welcome email") + .subscription( + JourneyTemplateCreateRequest.Notification.Subscription + .builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .providerKey("x") + .state("state") + .build() + ) + .build() + ) + + journeyTemplateGetResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun retrieve() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.journeys().templates() + + val journeyTemplateGetResponse = + templateService.retrieve( + TemplateRetrieveParams.builder().templateId("x").notificationId("x").build() + ) + + journeyTemplateGetResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun list() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.journeys().templates() + + val journeyTemplateListResponse = + templateService.list( + TemplateListParams.builder().templateId("x").cursor("cursor").limit(1L).build() + ) + + journeyTemplateListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun archive() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.journeys().templates() + + templateService.archive( + TemplateArchiveParams.builder().templateId("x").notificationId("x").build() + ) + } + + @Disabled("Mock server tests are disabled") + @Test + fun listVersions() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.journeys().templates() + + val notificationTemplateVersionListResponse = + templateService.listVersions( + TemplateListVersionsParams.builder().templateId("x").notificationId("x").build() + ) + + notificationTemplateVersionListResponse.validate() + } + + @Disabled("Mock server tests are disabled") + @Test + fun publish() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.journeys().templates() + + templateService.publish( + TemplatePublishParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplatePublishRequest( + JourneyTemplatePublishRequest.builder().version("v321669910225").build() + ) + .build() + ) + } + + @Disabled("Mock server tests are disabled") + @Test + fun replace() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.journeys().templates() + + val journeyTemplateGetResponse = + templateService.replace( + TemplateReplaceParams.builder() + .templateId("x") + .notificationId("x") + .journeyTemplateReplaceRequest( + JourneyTemplateReplaceRequest.builder() + .notification( + JourneyTemplateReplaceRequest.Notification.builder() + .brand( + JourneyTemplateReplaceRequest.Notification.Brand.builder() + .id("id") + .build() + ) + .content( + JourneyTemplateReplaceRequest.Notification.Content.builder() + .addElement( + ElementalTextNodeWithType.builder() + .addChannel("string") + .if_("if") + .loop("loop") + .ref("ref") + .type(ElementalTextNodeWithType.Type.TEXT) + .build() + ) + .version( + JourneyTemplateReplaceRequest.Notification.Content + .Version + ._2022_01_01 + ) + .scope( + JourneyTemplateReplaceRequest.Notification.Content + .Scope + .DEFAULT + ) + .build() + ) + .name("name") + .subscription( + JourneyTemplateReplaceRequest.Notification.Subscription + .builder() + .topicId("topic_id") + .build() + ) + .addTag("string") + .build() + ) + .state("state") + .build() + ) + .build() + ) + + journeyTemplateGetResponse.validate() + } +} diff --git a/courier-java-core/src/test/kotlin/com/courier/services/blocking/tenants/TemplateServiceTest.kt b/courier-java-core/src/test/kotlin/com/courier/services/blocking/tenants/TemplateServiceTest.kt index db7c0cfe..1e8f2f49 100644 --- a/courier-java-core/src/test/kotlin/com/courier/services/blocking/tenants/TemplateServiceTest.kt +++ b/courier-java-core/src/test/kotlin/com/courier/services/blocking/tenants/TemplateServiceTest.kt @@ -12,6 +12,7 @@ import com.courier.models.MessageRouting import com.courier.models.tenants.PostTenantTemplatePublishRequest import com.courier.models.tenants.PutTenantTemplateRequest import com.courier.models.tenants.TenantTemplateInput +import com.courier.models.tenants.templates.TemplateDeleteParams import com.courier.models.tenants.templates.TemplateListParams import com.courier.models.tenants.templates.TemplatePublishParams import com.courier.models.tenants.templates.TemplateReplaceParams @@ -56,6 +57,17 @@ internal class TemplateServiceTest { templates.validate() } + @Disabled("Mock server tests are disabled") + @Test + fun delete() { + val client = CourierOkHttpClient.builder().apiKey("My API Key").build() + val templateService = client.tenants().templates() + + templateService.delete( + TemplateDeleteParams.builder().tenantId("tenant_id").templateId("template_id").build() + ) + } + @Disabled("Mock server tests are disabled") @Test fun publish() { diff --git a/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt b/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt index 316809f0..c17a25a0 100644 --- a/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt +++ b/courier-java-proguard-test/src/test/kotlin/com/courier/proguard/ProGuardCompatibilityTest.kt @@ -75,7 +75,7 @@ internal class ProGuardCompatibilityTest { fun sendMessageResponseRoundtrip() { val jsonMapper = jsonMapper() val sendMessageResponse = - SendMessageResponse.builder().requestId("1-65f240a0-47a6a120c8374de9bcf9f22c").build() + SendMessageResponse.builder().requestId("1-69f561d3-7ad9d453fb6a7012efc2c5ad").build() val roundtrippedSendMessageResponse = jsonMapper.readValue(