diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 97699ccc4..2faf62100 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,7 +14,7 @@ on:
jobs:
lint:
- timeout-minutes: 10
+ timeout-minutes: 15
name: lint
runs-on: ${{ github.repository == 'stainless-sdks/orb-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
@@ -36,8 +36,33 @@ jobs:
- name: Run lints
run: ./scripts/lint
+
+ build:
+ timeout-minutes: 15
+ name: build
+ runs-on: ${{ github.repository == 'stainless-sdks/orb-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up Java
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: |
+ 8
+ 21
+ cache: gradle
+
+ - name: Set up Gradle
+ uses: gradle/actions/setup-gradle@v4
+
+ - name: Build SDK
+ run: ./scripts/build
+
test:
- timeout-minutes: 10
+ timeout-minutes: 15
name: test
runs-on: ${{ github.repository == 'stainless-sdks/orb-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }}
if: github.event_name == 'push' || github.event.pull_request.head.repo.fork
diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml
index 0265f1b1c..9b8da594d 100644
--- a/.github/workflows/publish-sonatype.yml
+++ b/.github/workflows/publish-sonatype.yml
@@ -22,7 +22,7 @@ jobs:
distribution: temurin
java-version: |
8
- 17
+ 21
cache: gradle
- name: Set up Gradle
@@ -33,7 +33,7 @@ jobs:
export -- GPG_SIGNING_KEY_ID
printenv -- GPG_SIGNING_KEY | gpg --batch --passphrase-fd 3 --import 3<<< "$GPG_SIGNING_PASSWORD"
GPG_SIGNING_KEY_ID="$(gpg --with-colons --list-keys | awk -F : -- '/^pub:/ { getline; print "0x" substr($10, length($10) - 7) }')"
- ./gradlew publishAndReleaseToMavenCentral -Dorg.gradle.jvmargs="-Xmx8g" --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache
+ ./gradlew publishAndReleaseToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD" --no-configuration-cache
env:
SONATYPE_USERNAME: ${{ secrets.ORB_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.ORB_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }}
diff --git a/.gitignore b/.gitignore
index 4e81838d6..b1346e6d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,6 @@
.gradle
.idea
.kotlin
-build
+build/
codegen.log
kls_database.db
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index caf148712..de0960aba 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "1.11.0"
+ ".": "1.12.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index c03739d1c..b3a9d31c0 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
configured_endpoints: 118
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-4f31d46f5ba187fc4d702c9f9f1573dacb891edbd086f935707578d7c4f5fed8.yml
-openapi_spec_hash: 25b1019f20a47b8af665aae5f8fd0025
-config_hash: 5135e9237207028f293049a77428c775
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-59c57f1cbc067a477f6bf673882c28065e01418b86fcff390bba0d4438c58105.yml
+openapi_spec_hash: 4da2681664f766985d1c20df40240cd9
+config_hash: 05c94c0e6dbeab2c9b554c2e0d6371a0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c16efd4eb..bd61b2eed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,85 @@
# Changelog
+## 1.12.0 (2025-12-18)
+
+Full Changelog: [v1.11.0...v1.12.0](https://github.com/orbcorp/orb-kotlin/compare/v1.11.0...v1.12.0)
+
+### ⚠ BREAKING CHANGES
+
+* **api:** define shared model ConversionRateConfig
+
+### Features
+
+* add retryable exception ([6bf3387](https://github.com/orbcorp/orb-kotlin/commit/6bf3387e9efe151b2db48c51a454f4ac9abb03e1))
+* **api:** api update ([e4e8d24](https://github.com/orbcorp/orb-kotlin/commit/e4e8d24b25879216965e7c55c5e23ab3bbbc69f8))
+* **api:** api update ([68203a3](https://github.com/orbcorp/orb-kotlin/commit/68203a34d2c36b47aecb227b408452f65f4db572))
+* **api:** api update ([012b348](https://github.com/orbcorp/orb-kotlin/commit/012b348959220609a650011f38e967b55aa6c906))
+* **api:** api update ([bbe220c](https://github.com/orbcorp/orb-kotlin/commit/bbe220c8813cd6a5c491da043f0b39cffe06edca))
+* **api:** api update ([cfe2c88](https://github.com/orbcorp/orb-kotlin/commit/cfe2c8868aead2144f69f0b04e304de948adbf8d))
+* **api:** api update ([74b29ea](https://github.com/orbcorp/orb-kotlin/commit/74b29eac5934c4d52380859df2df42a5c6b8db46))
+* **api:** api update ([af8a41f](https://github.com/orbcorp/orb-kotlin/commit/af8a41f71ca341c4ca6362158c555810a217ec49))
+* **api:** api update ([0f366e8](https://github.com/orbcorp/orb-kotlin/commit/0f366e8c6196b679186999278cb93686eda3c6a9))
+* **api:** api update ([2eb59cf](https://github.com/orbcorp/orb-kotlin/commit/2eb59cfcbe3b452746ef31a5f7c89f43276cffe5))
+* **api:** api update ([99993b1](https://github.com/orbcorp/orb-kotlin/commit/99993b17f65917b21e1f87b14699f5ac5cb63e1e))
+* **api:** api update ([914623a](https://github.com/orbcorp/orb-kotlin/commit/914623ae6f05e8ea28761331aba3b36676f10a99))
+* **api:** api update ([fd82100](https://github.com/orbcorp/orb-kotlin/commit/fd821005e293869c0199d3d5261f3a806df74e41))
+* **api:** api update ([9c2441e](https://github.com/orbcorp/orb-kotlin/commit/9c2441e3488e02d6e3f130dbbc1e1a9c821ac15d))
+* **api:** api update ([680265b](https://github.com/orbcorp/orb-kotlin/commit/680265b0add2f0c05eee02f1410cda5d14bd758b))
+* **api:** api update ([a1a92f4](https://github.com/orbcorp/orb-kotlin/commit/a1a92f48d35131e22f8e4e9ce51f6a31c8445277))
+* **api:** api update ([83ad00c](https://github.com/orbcorp/orb-kotlin/commit/83ad00cb56d547e695b01e7e02e923247856f3c8))
+* **api:** api update ([42c2d10](https://github.com/orbcorp/orb-kotlin/commit/42c2d10e801b46d82791cb26511cc237c5a9614a))
+* **api:** api update ([f6987c9](https://github.com/orbcorp/orb-kotlin/commit/f6987c9fd19277bfdb124bf896a74584ae69090b))
+* **api:** api update ([a58f47b](https://github.com/orbcorp/orb-kotlin/commit/a58f47b9e018a45680b2819cbc6ff9945779573d))
+* **api:** api update ([0285f3a](https://github.com/orbcorp/orb-kotlin/commit/0285f3a1dd36ff49e345c862ac5dd8e714019df1))
+* **api:** api update ([6d42811](https://github.com/orbcorp/orb-kotlin/commit/6d42811246f63cd57f9c2b9917a291ba9ef5b6ae))
+* **api:** api update ([93761f0](https://github.com/orbcorp/orb-kotlin/commit/93761f0a10e3a553c7ca56701f746de784ee2516))
+* **api:** api update ([4c2a026](https://github.com/orbcorp/orb-kotlin/commit/4c2a026cdd5327b5d58a42f2ae81975b5a8b6821))
+* **api:** api update ([11cfcca](https://github.com/orbcorp/orb-kotlin/commit/11cfcca024a9abce1fbe8d3097c3d3aeb66eee34))
+* **api:** api update ([a9326c1](https://github.com/orbcorp/orb-kotlin/commit/a9326c1fc925f51377493ccb1d50cdbcd444df07))
+* **api:** api update ([c427776](https://github.com/orbcorp/orb-kotlin/commit/c427776d050d0cc71128bbd7c1f985bf70df342c))
+* **api:** api update ([c4c96c6](https://github.com/orbcorp/orb-kotlin/commit/c4c96c6e42c74985376828b8efe6d03e0dcb91b5))
+* **api:** api update ([a05fab4](https://github.com/orbcorp/orb-kotlin/commit/a05fab462983dba1d6c3755e1e1a65d24a527f60))
+* **api:** api update ([d631c4d](https://github.com/orbcorp/orb-kotlin/commit/d631c4dd6dbf3657a11731eebdb772ed770ad154))
+* **api:** api update ([f06d033](https://github.com/orbcorp/orb-kotlin/commit/f06d033e7331f839b77ae33d33b878be2c797e5f))
+* **api:** api update ([e2b7b1e](https://github.com/orbcorp/orb-kotlin/commit/e2b7b1ee8a2594a363552c3289326b63a87112ec))
+* **api:** api update ([a790d45](https://github.com/orbcorp/orb-kotlin/commit/a790d458789e5a7336dc8510510b593b0d36ce73))
+* **api:** api update ([ee76ab8](https://github.com/orbcorp/orb-kotlin/commit/ee76ab871131d964501afbc390d2ba11595003bd))
+* **api:** api update ([6180a95](https://github.com/orbcorp/orb-kotlin/commit/6180a95d21214a3bf90989d6a80e55cf2c066fc8))
+* **api:** api update ([d43255b](https://github.com/orbcorp/orb-kotlin/commit/d43255b2f3030d1575c1c88898e1e1be202a13b6))
+* **api:** define shared model ConversionRateConfig ([32b3512](https://github.com/orbcorp/orb-kotlin/commit/32b35124936f5fea58bf91d92313b242f0d56e97))
+* **client:** ensure compat with proguard ([a21fc50](https://github.com/orbcorp/orb-kotlin/commit/a21fc50739926011c56bb30b47999d83bf7462e1))
+* **client:** expose sleeper option ([1bc7983](https://github.com/orbcorp/orb-kotlin/commit/1bc798369b1883ba86b50ac4829ccb9f5331bca5))
+* extract minimum composite to type ([c89ade2](https://github.com/orbcorp/orb-kotlin/commit/c89ade2708c48dfd327c4260ab1afe01e051e8c9))
+
+
+### Bug Fixes
+
+* **ci:** use java-version 21 for publish step ([efc7891](https://github.com/orbcorp/orb-kotlin/commit/efc789114af507dd96e591c18696a07dffad9af6))
+* **client:** deserialization of empty objects ([d4ef4ac](https://github.com/orbcorp/orb-kotlin/commit/d4ef4acd10993041451835b56cf0d1ce4d145f71))
+* **client:** ensure single timer is created per client ([1bc7983](https://github.com/orbcorp/orb-kotlin/commit/1bc798369b1883ba86b50ac4829ccb9f5331bca5))
+* **client:** incorrect `getPackageVersion` impl ([1612dd1](https://github.com/orbcorp/orb-kotlin/commit/1612dd121630d64f7d0ba6cfad7807e38765eda3))
+* **client:** multi-value header serialization ([bdc7d3a](https://github.com/orbcorp/orb-kotlin/commit/bdc7d3aa262fe9d79e9ce81dbc79b4ad7ac748eb))
+* **client:** r8 support ([4d46e62](https://github.com/orbcorp/orb-kotlin/commit/4d46e6201e6bf0a1963f05e3982ecc97bcb9519c))
+* **schema:** Rename unit price type to avoid naming conflict ([25c6f8c](https://github.com/orbcorp/orb-kotlin/commit/25c6f8c58010e5c2dd909f8161c8fee5465f2847))
+
+
+### Chores
+
+* **internal:** bump ci test timeout ([c9b431a](https://github.com/orbcorp/orb-kotlin/commit/c9b431af1e09f27dd08de5d1b247b72f70d160ae))
+* **internal:** change some comment formatting ([537aba1](https://github.com/orbcorp/orb-kotlin/commit/537aba177c709243ce291115eb15e8c1fd0adfa4))
+* **internal:** codegen related update ([b0ad475](https://github.com/orbcorp/orb-kotlin/commit/b0ad475dd5023f009b7d8a9a111a1b09c2e9f433))
+* **internal:** codegen related update ([844eb52](https://github.com/orbcorp/orb-kotlin/commit/844eb52c3959f68a8c6230accf8e570edcd553e4))
+* **internal:** codegen related update ([3239df5](https://github.com/orbcorp/orb-kotlin/commit/3239df52ca72a667fccc76f7bdf4799644b8322b))
+* **internal:** codegen related update ([b604e38](https://github.com/orbcorp/orb-kotlin/commit/b604e38e11b64d22569de6c59c7e40c02e048b9e))
+* **internal:** codegen related update ([936fe66](https://github.com/orbcorp/orb-kotlin/commit/936fe660fab9ecefb656d1db54b3288ec14fb235))
+* **internal:** codegen related update ([d06f656](https://github.com/orbcorp/orb-kotlin/commit/d06f6564fcaeaf124295a7cc5db061e7092e4771))
+* **internal:** reduce proguard ci logging ([ba337ee](https://github.com/orbcorp/orb-kotlin/commit/ba337ee683dea8296441855e1c5583c86bfa7f04))
+
+
+### Documentation
+
+* remove `$` for better copy-pasteabality ([7e95cda](https://github.com/orbcorp/orb-kotlin/commit/7e95cda57ad7eef980190010d8c68db1fb7f9eb3))
+
## 1.11.0 (2025-07-26)
Full Changelog: [v1.10.0...v1.11.0](https://github.com/orbcorp/orb-kotlin/compare/v1.10.0...v1.11.0)
diff --git a/README.md b/README.md
index a0e454c5b..5077e62fe 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-[](https://central.sonatype.com/artifact/com.withorb.api/orb-kotlin/1.11.0)
+[](https://central.sonatype.com/artifact/com.withorb.api/orb-kotlin/1.12.0)
@@ -19,7 +19,7 @@ The REST API documentation can be found on [docs.withorb.com](https://docs.witho
### Gradle
```kotlin
-implementation("com.withorb.api:orb-kotlin:1.11.0")
+implementation("com.withorb.api:orb-kotlin:1.12.0")
```
### Maven
@@ -28,7 +28,7 @@ implementation("com.withorb.api:orb-kotlin:1.11.0")
com.withorb.api
orb-kotlin
- 1.11.0
+ 1.12.0
```
@@ -229,6 +229,8 @@ The SDK throws custom unchecked exception types:
- [`OrbIoException`](orb-kotlin-core/src/main/kotlin/com/withorb/api/errors/OrbIoException.kt): I/O networking errors.
+- [`OrbRetryableException`](orb-kotlin-core/src/main/kotlin/com/withorb/api/errors/OrbRetryableException.kt): Generic error indicating a failure that could be retried by the client.
+
- [`OrbInvalidDataException`](orb-kotlin-core/src/main/kotlin/com/withorb/api/errors/OrbInvalidDataException.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.
- [`OrbException`](orb-kotlin-core/src/main/kotlin/com/withorb/api/errors/OrbException.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.
@@ -293,13 +295,13 @@ The SDK uses the standard [OkHttp logging interceptor](https://github.com/square
Enable logging by setting the `ORB_LOG` environment variable to `info`:
```sh
-$ export ORB_LOG=info
+export ORB_LOG=info
```
Or to `debug` for more verbose logging:
```sh
-$ export ORB_LOG=debug
+export ORB_LOG=debug
```
## Webhook Verification
@@ -312,6 +314,12 @@ both of which will raise an error if the signature is invalid.
Note that the `body` parameter must be the raw JSON string sent from the server (do not parse it first).
The `.unwrap()` method can parse this JSON for you.
+## 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 `orb-kotlin-core` is published with a [configuration file](orb-kotlin-core/src/main/resources/META-INF/proguard/orb-kotlin-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.
diff --git a/build.gradle.kts b/build.gradle.kts
index 26526fba0..4fd74a10b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,4 +1,16 @@
allprojects {
group = "com.withorb.api"
- version = "1.11.0" // x-release-please-version
+ version = "1.12.0" // x-release-please-version
+}
+
+subprojects {
+ // These are populated with dependencies by `buildSrc` scripts.
+ tasks.register("format") {
+ group = "Verification"
+ description = "Formats all source files."
+ }
+ tasks.register("lint") {
+ group = "Verification"
+ description = "Verifies all source files are formatted."
+ }
}
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 778c89de5..c6dc92ec5 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -10,7 +10,6 @@ repositories {
}
dependencies {
- implementation("com.diffplug.spotless:spotless-plugin-gradle:7.0.2")
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20")
implementation("com.vanniktech:gradle-maven-publish-plugin:0.28.0")
}
diff --git a/buildSrc/src/main/kotlin/orb.java.gradle.kts b/buildSrc/src/main/kotlin/orb.java.gradle.kts
index dfbacb86e..70fc33f41 100644
--- a/buildSrc/src/main/kotlin/orb.java.gradle.kts
+++ b/buildSrc/src/main/kotlin/orb.java.gradle.kts
@@ -1,24 +1,13 @@
-import com.diffplug.gradle.spotless.SpotlessExtension
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
plugins {
`java-library`
- id("com.diffplug.spotless")
}
repositories {
mavenCentral()
}
-configure {
- java {
- importOrder()
- removeUnusedImports()
- palantirJavaFormat()
- toggleOffOn()
- }
-}
-
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
@@ -53,3 +42,86 @@ tasks.withType().configureEach {
exceptionFormat = TestExceptionFormat.FULL
}
}
+
+val palantir by configurations.creating
+dependencies {
+ palantir("com.palantir.javaformat:palantir-java-format:2.73.0")
+}
+
+fun registerPalantir(
+ name: String,
+ description: String,
+) {
+ val javaName = "${name}Java"
+ tasks.register(javaName) {
+ group = "Verification"
+ this.description = description
+
+ classpath = palantir
+ mainClass = "com.palantir.javaformat.java.Main"
+
+ // Avoid an `IllegalAccessError` on Java 9+.
+ jvmArgs(
+ "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
+ "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED",
+ "--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED",
+ "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
+ "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+ )
+
+ // Use paths relative to the current module.
+ val argumentFile =
+ project.layout.buildDirectory.file("palantir-$name-args.txt").get().asFile
+ val lastRunTimeFile =
+ project.layout.buildDirectory.file("palantir-$name-last-run.txt").get().asFile
+
+ // Read the time when this task was last executed for this module (if ever).
+ val lastRunTime = lastRunTimeFile.takeIf { it.exists() }?.readText()?.toLongOrNull() ?: 0L
+
+ // Use a `fileTree` relative to the module's source directory.
+ val javaFiles = project.fileTree("src") { include("**/*.java") }
+
+ // Determine if any files need to be formatted or linted and continue only if there is at least
+ // one file.
+ onlyIf { javaFiles.any { it.lastModified() > lastRunTime } }
+
+ inputs.files(javaFiles)
+
+ doFirst {
+ // Create the argument file and set the preferred formatting style.
+ argumentFile.parentFile.mkdirs()
+ argumentFile.writeText("--palantir\n")
+
+ if (name == "lint") {
+ // For lint, do a dry run, so no files are modified. Set the exit code to 1 (instead of
+ // the default 0) if any files need to be formatted, indicating that linting has failed.
+ argumentFile.appendText("--dry-run\n")
+ argumentFile.appendText("--set-exit-if-changed\n")
+ } else {
+ // `--dry-run` and `--replace` (for in-place formatting) are mutually exclusive.
+ argumentFile.appendText("--replace\n")
+ }
+
+ // Write the modified files to the argument file.
+ javaFiles.filter { it.lastModified() > lastRunTime }
+ .forEach { argumentFile.appendText("${it.absolutePath}\n") }
+ }
+
+ doLast {
+ // Record the last execution time for later up-to-date checking.
+ lastRunTimeFile.writeText(System.currentTimeMillis().toString())
+ }
+
+ // Pass the argument file using the @ symbol
+ args = listOf("@${argumentFile.absolutePath}")
+
+ outputs.upToDateWhen { javaFiles.none { it.lastModified() > lastRunTime } }
+ }
+
+ tasks.named(name) {
+ dependsOn(tasks.named(javaName))
+ }
+}
+
+registerPalantir(name = "format", description = "Formats all Java source files.")
+registerPalantir(name = "lint", description = "Verifies all Java source files are formatted.")
diff --git a/buildSrc/src/main/kotlin/orb.kotlin.gradle.kts b/buildSrc/src/main/kotlin/orb.kotlin.gradle.kts
index 2d4a5c55c..b908b3bed 100644
--- a/buildSrc/src/main/kotlin/orb.kotlin.gradle.kts
+++ b/buildSrc/src/main/kotlin/orb.kotlin.gradle.kts
@@ -1,4 +1,3 @@
-import com.diffplug.gradle.spotless.SpotlessExtension
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
@@ -7,6 +6,10 @@ plugins {
kotlin("jvm")
}
+repositories {
+ mavenCentral()
+}
+
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(21))
@@ -27,14 +30,77 @@ kotlin {
}
}
-configure {
- kotlin {
- ktfmt().kotlinlangStyle()
- toggleOffOn()
- }
-}
-
tasks.withType().configureEach {
systemProperty("junit.jupiter.execution.parallel.enabled", true)
systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent")
}
+
+val ktfmt by configurations.creating
+dependencies {
+ ktfmt("com.facebook:ktfmt:0.56")
+}
+
+fun registerKtfmt(
+ name: String,
+ description: String,
+) {
+ val kotlinName = "${name}Kotlin"
+ tasks.register(kotlinName) {
+ group = "Verification"
+ this.description = description
+
+ classpath = ktfmt
+ mainClass = "com.facebook.ktfmt.cli.Main"
+
+ // Use paths relative to the current module.
+ val argumentFile = project.layout.buildDirectory.file("ktfmt-$name-args.txt").get().asFile
+ val lastRunTimeFile =
+ project.layout.buildDirectory.file("ktfmt-$name-last-run.txt").get().asFile
+
+ // Read the time when this task was last executed for this module (if ever).
+ val lastRunTime = lastRunTimeFile.takeIf { it.exists() }?.readText()?.toLongOrNull() ?: 0L
+
+ // Use a `fileTree` relative to the module's source directory.
+ val kotlinFiles = project.fileTree("src") { include("**/*.kt") }
+
+ // Determine if any files need to be formatted or linted and continue only if there is at least
+ // one file (otherwise Ktfmt will fail).
+ onlyIf { kotlinFiles.any { it.lastModified() > lastRunTime } }
+
+ inputs.files(kotlinFiles)
+
+ doFirst {
+ // Create the argument file and set the preferred formatting style.
+ argumentFile.parentFile.mkdirs()
+ argumentFile.writeText("--kotlinlang-style\n")
+
+ if (name == "lint") {
+ // For lint, do a dry run, so no files are modified. Set the exit code to 1 (instead of
+ // the default 0) if any files need to be formatted, indicating that linting has failed.
+ argumentFile.appendText("--dry-run\n")
+ argumentFile.appendText("--set-exit-if-changed\n")
+ }
+
+ // Write the modified files to the argument file.
+ kotlinFiles.filter { it.lastModified() > lastRunTime }
+ .forEach { argumentFile.appendText("${it.absolutePath}\n") }
+ }
+
+ doLast {
+ // Record the last execution time for later up-to-date checking.
+ lastRunTimeFile.writeText(System.currentTimeMillis().toString())
+ }
+
+ // Pass the argument file using the @ symbol
+ args = listOf("@${argumentFile.absolutePath}")
+
+ outputs.upToDateWhen { kotlinFiles.none { it.lastModified() > lastRunTime } }
+ }
+
+ tasks.named(name) {
+ dependsOn(tasks.named(kotlinName))
+ }
+}
+
+registerKtfmt(name = "format", description = "Formats all Kotlin source files.")
+registerKtfmt(name = "lint", description = "Verifies all Kotlin source files are formatted.")
diff --git a/examples/.keep b/examples/.keep
deleted file mode 100644
index d8c73e937..000000000
--- a/examples/.keep
+++ /dev/null
@@ -1,4 +0,0 @@
-File generated from our OpenAPI spec by Stainless.
-
-This directory can be used to store example files demonstrating usage of this SDK.
-It is ignored by Stainless code generation and its content (other than this keep file) won't be touched.
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index ff76593f6..6680f9ce9 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -4,12 +4,13 @@ org.gradle.parallel=true
org.gradle.daemon=false
# These options improve our compilation and test performance. They are inherited by the Kotlin daemon.
org.gradle.jvmargs=\
- -Xms1g \
- -Xmx4g \
+ -Xms2g \
+ -Xmx8g \
-XX:+UseParallelGC \
-XX:InitialCodeCacheSize=256m \
-XX:ReservedCodeCacheSize=1G \
- -XX:MetaspaceSize=256m \
+ -XX:MetaspaceSize=512m \
+ -XX:MaxMetaspaceSize=2G \
-XX:TieredStopAtLevel=1 \
-XX:GCTimeRatio=4 \
-XX:CICompilerCount=4 \
diff --git a/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OkHttpClient.kt b/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OkHttpClient.kt
index e11a7c94e..093faa347 100644
--- a/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OkHttpClient.kt
+++ b/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OkHttpClient.kt
@@ -117,19 +117,19 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC
val builder = Request.Builder().url(toUrl()).method(method.name, body)
headers.names().forEach { name ->
- headers.values(name).forEach { builder.header(name, it) }
+ headers.values(name).forEach { builder.addHeader(name, it) }
}
if (
!headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0
) {
- builder.header(
+ builder.addHeader(
"X-Stainless-Read-Timeout",
Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(),
)
}
if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) {
- builder.header(
+ builder.addHeader(
"X-Stainless-Timeout",
Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(),
)
diff --git a/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClient.kt b/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClient.kt
index 13caa41b5..b9706f4b6 100644
--- a/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClient.kt
+++ b/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClient.kt
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper
import com.withorb.api.client.OrbClient
import com.withorb.api.client.OrbClientImpl
import com.withorb.api.core.ClientOptions
+import com.withorb.api.core.Sleeper
import com.withorb.api.core.Timeout
import com.withorb.api.core.http.Headers
import com.withorb.api.core.http.HttpClient
@@ -103,6 +104,17 @@ class OrbOkHttpClient private constructor() {
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }
+ /**
+ * The interface to use for delaying execution, like during retries.
+ *
+ * This is primarily useful for using fake delays in tests.
+ *
+ * Defaults to real execution delays.
+ *
+ * This class takes ownership of the sleeper and closes it when closed.
+ */
+ fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) }
+
/**
* The clock to use for operations that require timing, like retries.
*
diff --git a/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClientAsync.kt b/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClientAsync.kt
index bb1291a78..c53344999 100644
--- a/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClientAsync.kt
+++ b/orb-kotlin-client-okhttp/src/main/kotlin/com/withorb/api/client/okhttp/OrbOkHttpClientAsync.kt
@@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper
import com.withorb.api.client.OrbClientAsync
import com.withorb.api.client.OrbClientAsyncImpl
import com.withorb.api.core.ClientOptions
+import com.withorb.api.core.Sleeper
import com.withorb.api.core.Timeout
import com.withorb.api.core.http.Headers
import com.withorb.api.core.http.HttpClient
@@ -103,6 +104,17 @@ class OrbOkHttpClientAsync private constructor() {
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) }
+ /**
+ * The interface to use for delaying execution, like during retries.
+ *
+ * This is primarily useful for using fake delays in tests.
+ *
+ * Defaults to real execution delays.
+ *
+ * This class takes ownership of the sleeper and closes it when closed.
+ */
+ fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) }
+
/**
* The clock to use for operations that require timing, like retries.
*
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientAsyncImpl.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientAsyncImpl.kt
index f8e4e3018..33eade7ef 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientAsyncImpl.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientAsyncImpl.kt
@@ -152,7 +152,7 @@ class OrbClientAsyncImpl(private val clientOptions: ClientOptions) : OrbClientAs
override fun subscriptionChanges(): SubscriptionChangeServiceAsync = subscriptionChanges
- override fun close() = clientOptions.httpClient.close()
+ override fun close() = clientOptions.close()
class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
OrbClientAsync.WithRawResponse {
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientImpl.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientImpl.kt
index c5937e469..3d8a11b6e 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientImpl.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/client/OrbClientImpl.kt
@@ -145,7 +145,7 @@ class OrbClientImpl(private val clientOptions: ClientOptions) : OrbClient {
override fun subscriptionChanges(): SubscriptionChangeService = subscriptionChanges
- override fun close() = clientOptions.httpClient.close()
+ override fun close() = clientOptions.close()
class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) :
OrbClient.WithRawResponse {
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/ClientOptions.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/ClientOptions.kt
index b18610e24..64002c6f0 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/ClientOptions.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/ClientOptions.kt
@@ -19,6 +19,8 @@ private constructor(
* The HTTP client to use in the SDK.
*
* Use the one published in `orb-kotlin-client-okhttp` or implement your own.
+ *
+ * This class takes ownership of the client and closes it when closed.
*/
val httpClient: HttpClient,
/**
@@ -36,6 +38,16 @@ private constructor(
* needs to be overridden.
*/
val jsonMapper: JsonMapper,
+ /**
+ * The interface to use for delaying execution, like during retries.
+ *
+ * This is primarily useful for using fake delays in tests.
+ *
+ * Defaults to real execution delays.
+ *
+ * This class takes ownership of the sleeper and closes it when closed.
+ */
+ val sleeper: Sleeper,
/**
* The clock to use for operations that require timing, like retries.
*
@@ -127,6 +139,7 @@ private constructor(
private var httpClient: HttpClient? = null
private var checkJacksonVersionCompatibility: Boolean = true
private var jsonMapper: JsonMapper = jsonMapper()
+ private var sleeper: Sleeper? = null
private var clock: Clock = Clock.systemUTC()
private var baseUrl: String? = null
private var headers: Headers.Builder = Headers.builder()
@@ -141,6 +154,7 @@ private constructor(
httpClient = clientOptions.originalHttpClient
checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility
jsonMapper = clientOptions.jsonMapper
+ sleeper = clientOptions.sleeper
clock = clientOptions.clock
baseUrl = clientOptions.baseUrl
headers = clientOptions.headers.toBuilder()
@@ -156,6 +170,8 @@ private constructor(
* The HTTP client to use in the SDK.
*
* Use the one published in `orb-kotlin-client-okhttp` or implement your own.
+ *
+ * This class takes ownership of the client and closes it when closed.
*/
fun httpClient(httpClient: HttpClient) = apply {
this.httpClient = PhantomReachableClosingHttpClient(httpClient)
@@ -180,6 +196,17 @@ private constructor(
*/
fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper }
+ /**
+ * The interface to use for delaying execution, like during retries.
+ *
+ * This is primarily useful for using fake delays in tests.
+ *
+ * Defaults to real execution delays.
+ *
+ * This class takes ownership of the sleeper and closes it when closed.
+ */
+ fun sleeper(sleeper: Sleeper) = apply { this.sleeper = PhantomReachableSleeper(sleeper) }
+
/**
* The clock to use for operations that require timing, like retries.
*
@@ -364,6 +391,7 @@ private constructor(
*/
fun build(): ClientOptions {
val httpClient = checkRequired("httpClient", httpClient)
+ val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper())
val apiKey = checkRequired("apiKey", apiKey)
val headers = Headers.builder()
@@ -387,12 +415,14 @@ private constructor(
httpClient,
RetryingHttpClient.builder()
.httpClient(httpClient)
+ .sleeper(sleeper)
.clock(clock)
.maxRetries(maxRetries)
.idempotencyHeader("Idempotency-Key")
.build(),
checkJacksonVersionCompatibility,
jsonMapper,
+ sleeper,
clock,
baseUrl,
headers.build(),
@@ -405,4 +435,19 @@ private constructor(
)
}
}
+
+ /**
+ * Closes these client options, relinquishing any underlying resources.
+ *
+ * This is purposefully not inherited from [AutoCloseable] because the client options are
+ * long-lived and usually should not be synchronously closed via try-with-resources.
+ *
+ * It's also usually not necessary to call this method at all. the default client automatically
+ * releases threads and connections if they remain idle, but if you are writing an application
+ * that needs to aggressively release unused resources, then you may call this method.
+ */
+ fun close() {
+ httpClient.close()
+ sleeper.close()
+ }
}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/DefaultSleeper.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/DefaultSleeper.kt
new file mode 100644
index 000000000..8222607cb
--- /dev/null
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/DefaultSleeper.kt
@@ -0,0 +1,14 @@
+package com.withorb.api.core
+
+import java.time.Duration
+import kotlin.time.toKotlinDuration
+import kotlinx.coroutines.delay
+
+class DefaultSleeper : Sleeper {
+
+ override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis())
+
+ override suspend fun sleepAsync(duration: Duration) = delay(duration.toKotlinDuration())
+
+ override fun close() {}
+}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/PhantomReachableExecutorService.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/PhantomReachableExecutorService.kt
new file mode 100644
index 000000000..b4617be28
--- /dev/null
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/PhantomReachableExecutorService.kt
@@ -0,0 +1,58 @@
+package com.withorb.api.core
+
+import java.util.concurrent.Callable
+import java.util.concurrent.ExecutorService
+import java.util.concurrent.Future
+import java.util.concurrent.TimeUnit
+
+/**
+ * A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom
+ * reachable.
+ *
+ * This class ensures the [ExecutorService] is shut down even if the user forgets to do it.
+ */
+internal class PhantomReachableExecutorService(private val executorService: ExecutorService) :
+ ExecutorService {
+ init {
+ closeWhenPhantomReachable(this) { executorService.shutdown() }
+ }
+
+ override fun execute(command: Runnable) = executorService.execute(command)
+
+ override fun shutdown() = executorService.shutdown()
+
+ override fun shutdownNow(): MutableList = executorService.shutdownNow()
+
+ override fun isShutdown(): Boolean = executorService.isShutdown
+
+ override fun isTerminated(): Boolean = executorService.isTerminated
+
+ override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean =
+ executorService.awaitTermination(timeout, unit)
+
+ override fun submit(task: Callable): Future = executorService.submit(task)
+
+ override fun submit(task: Runnable, result: T): Future =
+ executorService.submit(task, result)
+
+ override fun submit(task: Runnable): Future<*> = executorService.submit(task)
+
+ override fun invokeAll(
+ tasks: MutableCollection>
+ ): MutableList> = executorService.invokeAll(tasks)
+
+ override fun invokeAll(
+ tasks: MutableCollection>,
+ timeout: Long,
+ unit: TimeUnit,
+ ): MutableList> = executorService.invokeAll(tasks, timeout, unit)
+
+ override fun invokeAny(tasks: MutableCollection>): T =
+ executorService.invokeAny(tasks)
+
+ override fun invokeAny(
+ tasks: MutableCollection>,
+ timeout: Long,
+ unit: TimeUnit,
+ ): T = executorService.invokeAny(tasks, timeout, unit)
+}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/PhantomReachableSleeper.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/PhantomReachableSleeper.kt
new file mode 100644
index 000000000..f3742aa51
--- /dev/null
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/PhantomReachableSleeper.kt
@@ -0,0 +1,21 @@
+package com.withorb.api.core
+
+import java.time.Duration
+
+/**
+ * A delegating wrapper around a [Sleeper] that closes it once it's only phantom reachable.
+ *
+ * This class ensures the [Sleeper] is closed even if the user forgets to do it.
+ */
+internal class PhantomReachableSleeper(private val sleeper: Sleeper) : Sleeper {
+
+ init {
+ closeWhenPhantomReachable(this, sleeper)
+ }
+
+ override fun sleep(duration: Duration) = sleeper.sleep(duration)
+
+ override suspend fun sleepAsync(duration: Duration) = sleeper.sleepAsync(duration)
+
+ override fun close() = sleeper.close()
+}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Properties.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Properties.kt
index 9045e4dbf..f0f63ba44 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Properties.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Properties.kt
@@ -2,7 +2,7 @@
package com.withorb.api.core
-import java.util.Properties
+import com.withorb.api.client.OrbClient
fun getOsArch(): String {
val osArch = System.getProperty("os.arch")
@@ -16,7 +16,7 @@ fun getOsArch(): String {
"x86_64" -> "x64"
"arm" -> "arm"
"aarch64" -> "arm64"
- else -> "other:${osArch}"
+ else -> "other:$osArch"
}
}
@@ -30,13 +30,12 @@ fun getOsName(): String {
osName.startsWith("Linux") -> "Linux"
osName.startsWith("Mac OS") -> "MacOS"
osName.startsWith("Windows") -> "Windows"
- else -> "Other:${osName}"
+ else -> "Other:$osName"
}
}
fun getOsVersion(): String = System.getProperty("os.version", "unknown")
-fun getPackageVersion(): String =
- Properties::class.java.`package`.implementationVersion ?: "unknown"
+fun getPackageVersion(): String = OrbClient::class.java.`package`.implementationVersion ?: "unknown"
fun getJavaVersion(): String = System.getProperty("java.version", "unknown")
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Sleeper.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Sleeper.kt
new file mode 100644
index 000000000..ae005b7b9
--- /dev/null
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Sleeper.kt
@@ -0,0 +1,17 @@
+package com.withorb.api.core
+
+import java.time.Duration
+
+/**
+ * An interface for delaying execution for a specified amount of time.
+ *
+ * Useful for testing and cleaning up resources.
+ */
+interface Sleeper : AutoCloseable {
+
+ /** Synchronously pauses execution for the given [duration]. */
+ fun sleep(duration: Duration)
+
+ /** Asynchronously pauses execution for the given [duration]. */
+ suspend fun sleepAsync(duration: Duration)
+}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Timeout.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Timeout.kt
index e5ed8356e..aa60df127 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Timeout.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Timeout.kt
@@ -141,10 +141,14 @@ private constructor(
return true
}
- return /* spotless:off */ other is Timeout && connect == other.connect && read == other.read && write == other.write && request == other.request /* spotless:on */
+ return other is Timeout &&
+ connect == other.connect &&
+ read == other.read &&
+ write == other.write &&
+ request == other.request
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(connect, read, write, request) /* spotless:on */
+ override fun hashCode(): Int = Objects.hash(connect, read, write, request)
override fun toString() =
"Timeout{connect=$connect, read=$read, write=$write, request=$request}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Utils.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Utils.kt
index 41ae5d3c4..597e7de7f 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Utils.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/Utils.kt
@@ -6,6 +6,7 @@ import com.withorb.api.core.http.Headers
import com.withorb.api.errors.OrbInvalidDataException
import java.util.Collections
import java.util.SortedMap
+import java.util.concurrent.locks.Lock
internal fun T?.getOrThrow(name: String): T =
this ?: throw OrbInvalidDataException("`${name}` is not present")
@@ -87,3 +88,19 @@ internal fun Headers.getRequiredHeader(name: String): String =
values(name).firstOrNull() ?: throw OrbInvalidDataException("Could not find $name header")
internal interface Enum
+
+/**
+ * Executes a suspending block of code while holding this lock.
+ *
+ * @param T the return type of the action
+ * @param action the suspending function to execute while holding the lock
+ * @return the result of executing the action
+ */
+internal suspend fun Lock.withLockAsync(action: suspend () -> T): T {
+ lock()
+ return try {
+ action()
+ } finally {
+ unlock()
+ }
+}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/http/RetryingHttpClient.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/http/RetryingHttpClient.kt
index 738ddfbae..37aadd1df 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/http/RetryingHttpClient.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/core/http/RetryingHttpClient.kt
@@ -1,8 +1,11 @@
package com.withorb.api.core.http
+import com.withorb.api.core.DefaultSleeper
import com.withorb.api.core.RequestOptions
+import com.withorb.api.core.Sleeper
import com.withorb.api.core.checkRequired
import com.withorb.api.errors.OrbIoException
+import com.withorb.api.errors.OrbRetryableException
import java.io.IOException
import java.time.Clock
import java.time.Duration
@@ -15,8 +18,6 @@ import java.util.concurrent.ThreadLocalRandom
import java.util.concurrent.TimeUnit
import kotlin.math.min
import kotlin.math.pow
-import kotlin.time.toKotlinDuration
-import kotlinx.coroutines.delay
class RetryingHttpClient
private constructor(
@@ -112,7 +113,10 @@ private constructor(
}
}
- override fun close() = httpClient.close()
+ override fun close() {
+ httpClient.close()
+ sleeper.close()
+ }
private fun isRetryable(request: HttpRequest): Boolean =
// Some requests, such as when a request body is being streamed, cannot be retried because
@@ -159,9 +163,10 @@ private constructor(
}
private fun shouldRetry(throwable: Throwable): Boolean =
- // Only retry IOException and OrbIoException, other exceptions are not intended to be
- // retried.
- throwable is IOException || throwable is OrbIoException
+ // Only retry known retryable exceptions, other exceptions are not intended to be retried.
+ throwable is IOException ||
+ throwable is OrbIoException ||
+ throwable is OrbRetryableException
private fun getRetryBackoffDuration(retries: Int, response: HttpResponse?): Duration {
// About the Retry-After header:
@@ -216,21 +221,14 @@ private constructor(
class Builder internal constructor() {
private var httpClient: HttpClient? = null
- private var sleeper: Sleeper =
- object : Sleeper {
-
- override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis())
-
- override suspend fun sleepAsync(duration: Duration) =
- delay(duration.toKotlinDuration())
- }
+ private var sleeper: Sleeper? = null
private var clock: Clock = Clock.systemUTC()
private var maxRetries: Int = 2
private var idempotencyHeader: String? = null
fun httpClient(httpClient: HttpClient) = apply { this.httpClient = httpClient }
- internal fun sleeper(sleeper: Sleeper) = apply { this.sleeper = sleeper }
+ fun sleeper(sleeper: Sleeper) = apply { this.sleeper = sleeper }
fun clock(clock: Clock) = apply { this.clock = clock }
@@ -241,17 +239,10 @@ private constructor(
fun build(): HttpClient =
RetryingHttpClient(
checkRequired("httpClient", httpClient),
- sleeper,
+ sleeper ?: DefaultSleeper(),
clock,
maxRetries,
idempotencyHeader,
)
}
-
- internal interface Sleeper {
-
- fun sleep(duration: Duration)
-
- suspend fun sleepAsync(duration: Duration)
- }
}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/errors/OrbRetryableException.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/errors/OrbRetryableException.kt
new file mode 100644
index 000000000..b775d950b
--- /dev/null
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/errors/OrbRetryableException.kt
@@ -0,0 +1,13 @@
+package com.withorb.api.errors
+
+/**
+ * Exception that indicates a transient error that can be retried.
+ *
+ * When this exception is thrown during an HTTP request, the SDK will automatically retry the
+ * request up to the maximum number of retries.
+ *
+ * @param message A descriptive error message
+ * @param cause The underlying cause of this exception, if any
+ */
+class OrbRetryableException constructor(message: String? = null, cause: Throwable? = null) :
+ OrbException(message, cause)
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AccountingProviderConfig.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AccountingProviderConfig.kt
index c88d31918..1883cd288 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AccountingProviderConfig.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AccountingProviderConfig.kt
@@ -16,6 +16,7 @@ import java.util.Collections
import java.util.Objects
class AccountingProviderConfig
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val externalProviderId: JsonField,
private val providerType: JsonField,
@@ -203,12 +204,15 @@ private constructor(
return true
}
- return /* spotless:off */ other is AccountingProviderConfig && externalProviderId == other.externalProviderId && providerType == other.providerType && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AccountingProviderConfig &&
+ externalProviderId == other.externalProviderId &&
+ providerType == other.providerType &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(externalProviderId, providerType, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(externalProviderId, providerType, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Address.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Address.kt
index 61ba0c965..932fcb73f 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Address.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Address.kt
@@ -16,6 +16,7 @@ import java.util.Collections
import java.util.Objects
class Address
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val city: JsonField,
private val country: JsonField,
@@ -318,12 +319,19 @@ private constructor(
return true
}
- return /* spotless:off */ other is Address && city == other.city && country == other.country && line1 == other.line1 && line2 == other.line2 && postalCode == other.postalCode && state == other.state && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Address &&
+ city == other.city &&
+ country == other.country &&
+ line1 == other.line1 &&
+ line2 == other.line2 &&
+ postalCode == other.postalCode &&
+ state == other.state &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(city, country, line1, line2, postalCode, state, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(city, country, line1, line2, postalCode, state, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AddressInput.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AddressInput.kt
index b833dff70..a57985530 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AddressInput.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AddressInput.kt
@@ -15,6 +15,7 @@ import java.util.Collections
import java.util.Objects
class AddressInput
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val city: JsonField,
private val country: JsonField,
@@ -293,12 +294,19 @@ private constructor(
return true
}
- return /* spotless:off */ other is AddressInput && city == other.city && country == other.country && line1 == other.line1 && line2 == other.line2 && postalCode == other.postalCode && state == other.state && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AddressInput &&
+ city == other.city &&
+ country == other.country &&
+ line1 == other.line1 &&
+ line2 == other.line2 &&
+ postalCode == other.postalCode &&
+ state == other.state &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(city, country, line1, line2, postalCode, state, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(city, country, line1, line2, postalCode, state, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AdjustmentInterval.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AdjustmentInterval.kt
index fde27ce87..e9ffe44d3 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AdjustmentInterval.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AdjustmentInterval.kt
@@ -29,6 +29,7 @@ import java.util.Collections
import java.util.Objects
class AdjustmentInterval
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val id: JsonField,
private val adjustment: JsonField,
@@ -501,10 +502,16 @@ private constructor(
return true
}
- return /* spotless:off */ other is Adjustment && usageDiscount == other.usageDiscount && amountDiscount == other.amountDiscount && percentageDiscount == other.percentageDiscount && minimum == other.minimum && maximum == other.maximum /* spotless:on */
+ return other is Adjustment &&
+ usageDiscount == other.usageDiscount &&
+ amountDiscount == other.amountDiscount &&
+ percentageDiscount == other.percentageDiscount &&
+ minimum == other.minimum &&
+ maximum == other.maximum
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(usageDiscount, amountDiscount, percentageDiscount, minimum, maximum) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(usageDiscount, amountDiscount, percentageDiscount, minimum, maximum)
override fun toString(): String =
when {
@@ -638,12 +645,25 @@ private constructor(
return true
}
- return /* spotless:off */ other is AdjustmentInterval && id == other.id && adjustment == other.adjustment && appliesToPriceIntervalIds == other.appliesToPriceIntervalIds && endDate == other.endDate && startDate == other.startDate && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AdjustmentInterval &&
+ id == other.id &&
+ adjustment == other.adjustment &&
+ appliesToPriceIntervalIds == other.appliesToPriceIntervalIds &&
+ endDate == other.endDate &&
+ startDate == other.startDate &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(id, adjustment, appliesToPriceIntervalIds, endDate, startDate, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ id,
+ adjustment,
+ appliesToPriceIntervalIds,
+ endDate,
+ startDate,
+ additionalProperties,
+ )
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AffectedBlock.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AffectedBlock.kt
index 11b10c291..61d4b9b19 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AffectedBlock.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AffectedBlock.kt
@@ -6,20 +6,25 @@ 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.withorb.api.core.Enum
import com.withorb.api.core.ExcludeMissing
import com.withorb.api.core.JsonField
import com.withorb.api.core.JsonMissing
import com.withorb.api.core.JsonValue
+import com.withorb.api.core.checkKnown
import com.withorb.api.core.checkRequired
+import com.withorb.api.core.toImmutable
import com.withorb.api.errors.OrbInvalidDataException
import java.time.OffsetDateTime
import java.util.Collections
import java.util.Objects
class AffectedBlock
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val id: JsonField,
private val expiryDate: JsonField,
+ private val filters: JsonField>,
private val perUnitCostBasis: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -30,10 +35,13 @@ private constructor(
@JsonProperty("expiry_date")
@ExcludeMissing
expiryDate: JsonField = JsonMissing.of(),
+ @JsonProperty("filters")
+ @ExcludeMissing
+ filters: JsonField> = JsonMissing.of(),
@JsonProperty("per_unit_cost_basis")
@ExcludeMissing
perUnitCostBasis: JsonField = JsonMissing.of(),
- ) : this(id, expiryDate, perUnitCostBasis, mutableMapOf())
+ ) : this(id, expiryDate, filters, perUnitCostBasis, mutableMapOf())
/**
* @throws OrbInvalidDataException if the JSON field has an unexpected type or is unexpectedly
@@ -47,6 +55,12 @@ private constructor(
*/
fun expiryDate(): OffsetDateTime? = expiryDate.getNullable("expiry_date")
+ /**
+ * @throws OrbInvalidDataException 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 filters(): List = filters.getRequired("filters")
+
/**
* @throws OrbInvalidDataException if the JSON field has an unexpected type (e.g. if the server
* responded with an unexpected value).
@@ -69,6 +83,13 @@ private constructor(
@ExcludeMissing
fun _expiryDate(): JsonField = expiryDate
+ /**
+ * Returns the raw JSON value of [filters].
+ *
+ * Unlike [filters], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("filters") @ExcludeMissing fun _filters(): JsonField> = filters
+
/**
* Returns the raw JSON value of [perUnitCostBasis].
*
@@ -100,6 +121,7 @@ private constructor(
* ```kotlin
* .id()
* .expiryDate()
+ * .filters()
* .perUnitCostBasis()
* ```
*/
@@ -111,12 +133,14 @@ private constructor(
private var id: JsonField? = null
private var expiryDate: JsonField? = null
+ private var filters: JsonField>? = null
private var perUnitCostBasis: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
internal fun from(affectedBlock: AffectedBlock) = apply {
id = affectedBlock.id
expiryDate = affectedBlock.expiryDate
+ filters = affectedBlock.filters.map { it.toMutableList() }
perUnitCostBasis = affectedBlock.perUnitCostBasis
additionalProperties = affectedBlock.additionalProperties.toMutableMap()
}
@@ -144,6 +168,31 @@ private constructor(
this.expiryDate = expiryDate
}
+ fun filters(filters: List) = filters(JsonField.of(filters))
+
+ /**
+ * Sets [Builder.filters] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.filters] with a well-typed `List` value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun filters(filters: JsonField>) = apply {
+ this.filters = filters.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [Filter] to [filters].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addFilter(filter: Filter) = apply {
+ filters =
+ (filters ?: JsonField.of(mutableListOf())).also {
+ checkKnown("filters", it).add(filter)
+ }
+ }
+
fun perUnitCostBasis(perUnitCostBasis: String?) =
perUnitCostBasis(JsonField.ofNullable(perUnitCostBasis))
@@ -186,6 +235,7 @@ private constructor(
* ```kotlin
* .id()
* .expiryDate()
+ * .filters()
* .perUnitCostBasis()
* ```
*
@@ -195,6 +245,7 @@ private constructor(
AffectedBlock(
checkRequired("id", id),
checkRequired("expiryDate", expiryDate),
+ checkRequired("filters", filters).map { it.toImmutable() },
checkRequired("perUnitCostBasis", perUnitCostBasis),
additionalProperties.toMutableMap(),
)
@@ -209,6 +260,7 @@ private constructor(
id()
expiryDate()
+ filters().forEach { it.validate() }
perUnitCostBasis()
validated = true
}
@@ -229,22 +281,556 @@ private constructor(
internal fun validity(): Int =
(if (id.asKnown() == null) 0 else 1) +
(if (expiryDate.asKnown() == null) 0 else 1) +
+ (filters.asKnown()?.sumOf { it.validity().toInt() } ?: 0) +
(if (perUnitCostBasis.asKnown() == null) 0 else 1)
+ class Filter
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
+ private constructor(
+ private val field: JsonField,
+ private val operator: JsonField,
+ private val values: JsonField>,
+ private val additionalProperties: MutableMap,
+ ) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("field") @ExcludeMissing field: JsonField = JsonMissing.of(),
+ @JsonProperty("operator")
+ @ExcludeMissing
+ operator: JsonField = JsonMissing.of(),
+ @JsonProperty("values")
+ @ExcludeMissing
+ values: JsonField> = JsonMissing.of(),
+ ) : this(field, operator, values, mutableMapOf())
+
+ /**
+ * The property of the price to filter on.
+ *
+ * @throws OrbInvalidDataException 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 field(): Field = field.getRequired("field")
+
+ /**
+ * Should prices that match the filter be included or excluded.
+ *
+ * @throws OrbInvalidDataException 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 operator(): Operator = operator.getRequired("operator")
+
+ /**
+ * The IDs or values that match this filter.
+ *
+ * @throws OrbInvalidDataException 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 values(): List = values.getRequired("values")
+
+ /**
+ * Returns the raw JSON value of [field].
+ *
+ * Unlike [field], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("field") @ExcludeMissing fun _field(): JsonField = field
+
+ /**
+ * Returns the raw JSON value of [operator].
+ *
+ * Unlike [operator], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("operator") @ExcludeMissing fun _operator(): JsonField = operator
+
+ /**
+ * Returns the raw JSON value of [values].
+ *
+ * Unlike [values], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("values") @ExcludeMissing fun _values(): JsonField> = values
+
+ @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 [Filter].
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .field()
+ * .operator()
+ * .values()
+ * ```
+ */
+ fun builder() = Builder()
+ }
+
+ /** A builder for [Filter]. */
+ class Builder internal constructor() {
+
+ private var field: JsonField? = null
+ private var operator: JsonField? = null
+ private var values: JsonField>? = null
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ internal fun from(filter: Filter) = apply {
+ field = filter.field
+ operator = filter.operator
+ values = filter.values.map { it.toMutableList() }
+ additionalProperties = filter.additionalProperties.toMutableMap()
+ }
+
+ /** The property of the price to filter on. */
+ fun field(field: Field) = field(JsonField.of(field))
+
+ /**
+ * Sets [Builder.field] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.field] with a well-typed [Field] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun field(field: JsonField) = apply { this.field = field }
+
+ /** Should prices that match the filter be included or excluded. */
+ fun operator(operator: Operator) = operator(JsonField.of(operator))
+
+ /**
+ * Sets [Builder.operator] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.operator] with a well-typed [Operator] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun operator(operator: JsonField) = apply { this.operator = operator }
+
+ /** The IDs or values that match this filter. */
+ fun values(values: List) = values(JsonField.of(values))
+
+ /**
+ * Sets [Builder.values] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.values] with a well-typed `List` value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun values(values: JsonField>) = apply {
+ this.values = values.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [String] to [values].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addValue(value: String) = apply {
+ values =
+ (values ?: JsonField.of(mutableListOf())).also {
+ checkKnown("values", it).add(value)
+ }
+ }
+
+ 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 [Filter].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .field()
+ * .operator()
+ * .values()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): Filter =
+ Filter(
+ checkRequired("field", field),
+ checkRequired("operator", operator),
+ checkRequired("values", values).map { it.toImmutable() },
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Filter = apply {
+ if (validated) {
+ return@apply
+ }
+
+ field().validate()
+ operator().validate()
+ values()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ internal fun validity(): Int =
+ (field.asKnown()?.validity() ?: 0) +
+ (operator.asKnown()?.validity() ?: 0) +
+ (values.asKnown()?.size ?: 0)
+
+ /** The property of the price to filter on. */
+ class Field @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 {
+
+ val PRICE_ID = of("price_id")
+
+ val ITEM_ID = of("item_id")
+
+ val PRICE_TYPE = of("price_type")
+
+ val CURRENCY = of("currency")
+
+ val PRICING_UNIT_ID = of("pricing_unit_id")
+
+ fun of(value: String) = Field(JsonField.of(value))
+ }
+
+ /** An enum containing [Field]'s known values. */
+ enum class Known {
+ PRICE_ID,
+ ITEM_ID,
+ PRICE_TYPE,
+ CURRENCY,
+ PRICING_UNIT_ID,
+ }
+
+ /**
+ * An enum containing [Field]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Field] 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 {
+ PRICE_ID,
+ ITEM_ID,
+ PRICE_TYPE,
+ CURRENCY,
+ PRICING_UNIT_ID,
+ /**
+ * An enum member indicating that [Field] 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) {
+ PRICE_ID -> Value.PRICE_ID
+ ITEM_ID -> Value.ITEM_ID
+ PRICE_TYPE -> Value.PRICE_TYPE
+ CURRENCY -> Value.CURRENCY
+ PRICING_UNIT_ID -> Value.PRICING_UNIT_ID
+ 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 OrbInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ PRICE_ID -> Known.PRICE_ID
+ ITEM_ID -> Known.ITEM_ID
+ PRICE_TYPE -> Known.PRICE_TYPE
+ CURRENCY -> Known.CURRENCY
+ PRICING_UNIT_ID -> Known.PRICING_UNIT_ID
+ else -> throw OrbInvalidDataException("Unknown Field: $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 OrbInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw OrbInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Field = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ 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 Field && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ /** Should prices that match the filter be included or excluded. */
+ class Operator @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 {
+
+ val INCLUDES = of("includes")
+
+ val EXCLUDES = of("excludes")
+
+ fun of(value: String) = Operator(JsonField.of(value))
+ }
+
+ /** An enum containing [Operator]'s known values. */
+ enum class Known {
+ INCLUDES,
+ EXCLUDES,
+ }
+
+ /**
+ * An enum containing [Operator]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Operator] 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 {
+ INCLUDES,
+ EXCLUDES,
+ /**
+ * An enum member indicating that [Operator] 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) {
+ INCLUDES -> Value.INCLUDES
+ EXCLUDES -> Value.EXCLUDES
+ 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 OrbInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ INCLUDES -> Known.INCLUDES
+ EXCLUDES -> Known.EXCLUDES
+ else -> throw OrbInvalidDataException("Unknown Operator: $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 OrbInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw OrbInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Operator = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ 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 Operator && 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 Filter &&
+ field == other.field &&
+ operator == other.operator &&
+ values == other.values &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(field, operator, values, additionalProperties)
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "Filter{field=$field, operator=$operator, values=$values, additionalProperties=$additionalProperties}"
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
- return /* spotless:off */ other is AffectedBlock && id == other.id && expiryDate == other.expiryDate && perUnitCostBasis == other.perUnitCostBasis && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AffectedBlock &&
+ id == other.id &&
+ expiryDate == other.expiryDate &&
+ filters == other.filters &&
+ perUnitCostBasis == other.perUnitCostBasis &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(id, expiryDate, perUnitCostBasis, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(id, expiryDate, filters, perUnitCostBasis, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
override fun toString() =
- "AffectedBlock{id=$id, expiryDate=$expiryDate, perUnitCostBasis=$perUnitCostBasis, additionalProperties=$additionalProperties}"
+ "AffectedBlock{id=$id, expiryDate=$expiryDate, filters=$filters, perUnitCostBasis=$perUnitCostBasis, additionalProperties=$additionalProperties}"
}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AggregatedCost.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AggregatedCost.kt
index 1ed38a320..9a1d32c42 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AggregatedCost.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AggregatedCost.kt
@@ -19,6 +19,7 @@ import java.util.Collections
import java.util.Objects
class AggregatedCost
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val perPriceCosts: JsonField>,
private val subtotal: JsonField,
@@ -327,12 +328,25 @@ private constructor(
return true
}
- return /* spotless:off */ other is AggregatedCost && perPriceCosts == other.perPriceCosts && subtotal == other.subtotal && timeframeEnd == other.timeframeEnd && timeframeStart == other.timeframeStart && total == other.total && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AggregatedCost &&
+ perPriceCosts == other.perPriceCosts &&
+ subtotal == other.subtotal &&
+ timeframeEnd == other.timeframeEnd &&
+ timeframeStart == other.timeframeStart &&
+ total == other.total &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(perPriceCosts, subtotal, timeframeEnd, timeframeStart, total, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ perPriceCosts,
+ subtotal,
+ timeframeEnd,
+ timeframeStart,
+ total,
+ additionalProperties,
+ )
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Alert.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Alert.kt
index 08a5ca1fc..5f3c0a922 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Alert.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Alert.kt
@@ -26,6 +26,7 @@ import java.util.Objects
* Alerts created through the API can be scoped to either customers or subscriptions.
*/
class Alert
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val id: JsonField,
private val createdAt: JsonField,
@@ -587,6 +588,7 @@ private constructor(
/** The metric the alert applies to. */
class Metric
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val id: JsonField,
private val additionalProperties: MutableMap,
@@ -724,12 +726,12 @@ private constructor(
return true
}
- return /* spotless:off */ other is Metric && id == other.id && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Metric &&
+ id == other.id &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
private val hashCode: Int by lazy { Objects.hash(id, additionalProperties) }
- /* spotless:on */
override fun hashCode(): Int = hashCode
@@ -738,6 +740,7 @@ private constructor(
/** The plan the alert applies to. */
class Plan
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val id: JsonField,
private val externalPlanId: JsonField,
@@ -1001,12 +1004,17 @@ private constructor(
return true
}
- return /* spotless:off */ other is Plan && id == other.id && externalPlanId == other.externalPlanId && name == other.name && planVersion == other.planVersion && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Plan &&
+ id == other.id &&
+ externalPlanId == other.externalPlanId &&
+ name == other.name &&
+ planVersion == other.planVersion &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(id, externalPlanId, name, planVersion, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(id, externalPlanId, name, planVersion, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
@@ -1149,7 +1157,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is Type && value == other.value /* spotless:on */
+ return other is Type && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -1159,6 +1167,7 @@ private constructor(
/** Alert status is used to determine if an alert is currently in-alert or not. */
class BalanceAlertStatus
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val inAlert: JsonField,
private val thresholdValue: JsonField,
@@ -1349,12 +1358,15 @@ private constructor(
return true
}
- return /* spotless:off */ other is BalanceAlertStatus && inAlert == other.inAlert && thresholdValue == other.thresholdValue && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is BalanceAlertStatus &&
+ inAlert == other.inAlert &&
+ thresholdValue == other.thresholdValue &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(inAlert, thresholdValue, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(inAlert, thresholdValue, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
@@ -1367,12 +1379,37 @@ private constructor(
return true
}
- return /* spotless:off */ other is Alert && id == other.id && createdAt == other.createdAt && currency == other.currency && customer == other.customer && enabled == other.enabled && metric == other.metric && plan == other.plan && subscription == other.subscription && thresholds == other.thresholds && type == other.type && balanceAlertStatus == other.balanceAlertStatus && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Alert &&
+ id == other.id &&
+ createdAt == other.createdAt &&
+ currency == other.currency &&
+ customer == other.customer &&
+ enabled == other.enabled &&
+ metric == other.metric &&
+ plan == other.plan &&
+ subscription == other.subscription &&
+ thresholds == other.thresholds &&
+ type == other.type &&
+ balanceAlertStatus == other.balanceAlertStatus &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(id, createdAt, currency, customer, enabled, metric, plan, subscription, thresholds, type, balanceAlertStatus, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ id,
+ createdAt,
+ currency,
+ customer,
+ enabled,
+ metric,
+ plan,
+ subscription,
+ thresholds,
+ type,
+ balanceAlertStatus,
+ additionalProperties,
+ )
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForCustomerParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForCustomerParams.kt
index 5caf6d7e4..1a5474c90 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForCustomerParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForCustomerParams.kt
@@ -331,6 +331,7 @@ private constructor(
override fun _queryParams(): QueryParams = additionalQueryParams
class Body
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val currency: JsonField,
private val type: JsonField,
@@ -566,12 +567,16 @@ private constructor(
return true
}
- return /* spotless:off */ other is Body && currency == other.currency && type == other.type && thresholds == other.thresholds && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Body &&
+ currency == other.currency &&
+ type == other.type &&
+ thresholds == other.thresholds &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(currency, type, thresholds, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(currency, type, thresholds, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
@@ -702,7 +707,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is Type && value == other.value /* spotless:on */
+ return other is Type && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -715,10 +720,15 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertCreateForCustomerParams && customerId == other.customerId && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
+ return other is AlertCreateForCustomerParams &&
+ customerId == other.customerId &&
+ body == other.body &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(customerId, body, additionalHeaders, additionalQueryParams) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(customerId, body, additionalHeaders, additionalQueryParams)
override fun toString() =
"AlertCreateForCustomerParams{customerId=$customerId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForExternalCustomerParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForExternalCustomerParams.kt
index 0a34fcc70..4c85b34c6 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForExternalCustomerParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForExternalCustomerParams.kt
@@ -337,6 +337,7 @@ private constructor(
override fun _queryParams(): QueryParams = additionalQueryParams
class Body
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val currency: JsonField,
private val type: JsonField,
@@ -572,12 +573,16 @@ private constructor(
return true
}
- return /* spotless:off */ other is Body && currency == other.currency && type == other.type && thresholds == other.thresholds && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Body &&
+ currency == other.currency &&
+ type == other.type &&
+ thresholds == other.thresholds &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(currency, type, thresholds, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(currency, type, thresholds, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
@@ -708,7 +713,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is Type && value == other.value /* spotless:on */
+ return other is Type && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -721,10 +726,15 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertCreateForExternalCustomerParams && externalCustomerId == other.externalCustomerId && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
+ return other is AlertCreateForExternalCustomerParams &&
+ externalCustomerId == other.externalCustomerId &&
+ body == other.body &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(externalCustomerId, body, additionalHeaders, additionalQueryParams) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(externalCustomerId, body, additionalHeaders, additionalQueryParams)
override fun toString() =
"AlertCreateForExternalCustomerParams{externalCustomerId=$externalCustomerId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForSubscriptionParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForSubscriptionParams.kt
index 04771b7cc..d0130f701 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForSubscriptionParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertCreateForSubscriptionParams.kt
@@ -338,6 +338,7 @@ private constructor(
override fun _queryParams(): QueryParams = additionalQueryParams
class Body
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val thresholds: JsonField>,
private val type: JsonField,
@@ -572,12 +573,16 @@ private constructor(
return true
}
- return /* spotless:off */ other is Body && thresholds == other.thresholds && type == other.type && metricId == other.metricId && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Body &&
+ thresholds == other.thresholds &&
+ type == other.type &&
+ metricId == other.metricId &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(thresholds, type, metricId, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(thresholds, type, metricId, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
@@ -702,7 +707,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is Type && value == other.value /* spotless:on */
+ return other is Type && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -715,10 +720,15 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertCreateForSubscriptionParams && subscriptionId == other.subscriptionId && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
+ return other is AlertCreateForSubscriptionParams &&
+ subscriptionId == other.subscriptionId &&
+ body == other.body &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(subscriptionId, body, additionalHeaders, additionalQueryParams) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(subscriptionId, body, additionalHeaders, additionalQueryParams)
override fun toString() =
"AlertCreateForSubscriptionParams{subscriptionId=$subscriptionId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertDisableParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertDisableParams.kt
index 6dc4a86e2..11e03283a 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertDisableParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertDisableParams.kt
@@ -229,10 +229,22 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertDisableParams && alertConfigurationId == other.alertConfigurationId && subscriptionId == other.subscriptionId && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams && additionalBodyProperties == other.additionalBodyProperties /* spotless:on */
+ return other is AlertDisableParams &&
+ alertConfigurationId == other.alertConfigurationId &&
+ subscriptionId == other.subscriptionId &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams &&
+ additionalBodyProperties == other.additionalBodyProperties
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(alertConfigurationId, subscriptionId, additionalHeaders, additionalQueryParams, additionalBodyProperties) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(
+ alertConfigurationId,
+ subscriptionId,
+ additionalHeaders,
+ additionalQueryParams,
+ additionalBodyProperties,
+ )
override fun toString() =
"AlertDisableParams{alertConfigurationId=$alertConfigurationId, subscriptionId=$subscriptionId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertEnableParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertEnableParams.kt
index a57c1d49c..d92459458 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertEnableParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertEnableParams.kt
@@ -229,10 +229,22 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertEnableParams && alertConfigurationId == other.alertConfigurationId && subscriptionId == other.subscriptionId && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams && additionalBodyProperties == other.additionalBodyProperties /* spotless:on */
+ return other is AlertEnableParams &&
+ alertConfigurationId == other.alertConfigurationId &&
+ subscriptionId == other.subscriptionId &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams &&
+ additionalBodyProperties == other.additionalBodyProperties
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(alertConfigurationId, subscriptionId, additionalHeaders, additionalQueryParams, additionalBodyProperties) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(
+ alertConfigurationId,
+ subscriptionId,
+ additionalHeaders,
+ additionalQueryParams,
+ additionalBodyProperties,
+ )
override fun toString() =
"AlertEnableParams{alertConfigurationId=$alertConfigurationId, subscriptionId=$subscriptionId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPage.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPage.kt
index 684d17838..66c75b6b5 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPage.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPage.kt
@@ -119,10 +119,13 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertListPage && service == other.service && params == other.params && response == other.response /* spotless:on */
+ return other is AlertListPage &&
+ service == other.service &&
+ params == other.params &&
+ response == other.response
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(service, params, response) /* spotless:on */
+ override fun hashCode(): Int = Objects.hash(service, params, response)
override fun toString() = "AlertListPage{service=$service, params=$params, response=$response}"
}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageAsync.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageAsync.kt
index e4e0ec4ba..1376c6cdf 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageAsync.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageAsync.kt
@@ -119,10 +119,13 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertListPageAsync && service == other.service && params == other.params && response == other.response /* spotless:on */
+ return other is AlertListPageAsync &&
+ service == other.service &&
+ params == other.params &&
+ response == other.response
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(service, params, response) /* spotless:on */
+ override fun hashCode(): Int = Objects.hash(service, params, response)
override fun toString() =
"AlertListPageAsync{service=$service, params=$params, response=$response}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageResponse.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageResponse.kt
index 7921cc09f..249d4fd9e 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageResponse.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListPageResponse.kt
@@ -18,6 +18,7 @@ import java.util.Collections
import java.util.Objects
class AlertListPageResponse
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val data: JsonField>,
private val paginationMetadata: JsonField,
@@ -214,12 +215,15 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertListPageResponse && data == other.data && paginationMetadata == other.paginationMetadata && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AlertListPageResponse &&
+ data == other.data &&
+ paginationMetadata == other.paginationMetadata &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(data, paginationMetadata, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(data, paginationMetadata, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListParams.kt
index 5adbae16b..fb18cf24b 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertListParams.kt
@@ -14,7 +14,7 @@ import java.util.Objects
*
* The request must specify one of `customer_id`, `external_customer_id`, or `subscription_id`.
*
- * If querying by subscripion_id, the endpoint will return the subscription level alerts as well as
+ * If querying by subscription_id, the endpoint will return the subscription level alerts as well as
* the plan level alerts associated with the subscription.
*
* The list of alerts is ordered starting from the most recently created alert. This endpoint
@@ -291,10 +291,34 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertListParams && createdAtGt == other.createdAtGt && createdAtGte == other.createdAtGte && createdAtLt == other.createdAtLt && createdAtLte == other.createdAtLte && cursor == other.cursor && customerId == other.customerId && externalCustomerId == other.externalCustomerId && limit == other.limit && subscriptionId == other.subscriptionId && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
+ return other is AlertListParams &&
+ createdAtGt == other.createdAtGt &&
+ createdAtGte == other.createdAtGte &&
+ createdAtLt == other.createdAtLt &&
+ createdAtLte == other.createdAtLte &&
+ cursor == other.cursor &&
+ customerId == other.customerId &&
+ externalCustomerId == other.externalCustomerId &&
+ limit == other.limit &&
+ subscriptionId == other.subscriptionId &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(createdAtGt, createdAtGte, createdAtLt, createdAtLte, cursor, customerId, externalCustomerId, limit, subscriptionId, additionalHeaders, additionalQueryParams) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(
+ createdAtGt,
+ createdAtGte,
+ createdAtLt,
+ createdAtLte,
+ cursor,
+ customerId,
+ externalCustomerId,
+ limit,
+ subscriptionId,
+ additionalHeaders,
+ additionalQueryParams,
+ )
override fun toString() =
"AlertListParams{createdAtGt=$createdAtGt, createdAtGte=$createdAtGte, createdAtLt=$createdAtLt, createdAtLte=$createdAtLte, cursor=$cursor, customerId=$customerId, externalCustomerId=$externalCustomerId, limit=$limit, subscriptionId=$subscriptionId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertRetrieveParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertRetrieveParams.kt
index aa8516268..2a465a67b 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertRetrieveParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertRetrieveParams.kt
@@ -170,10 +170,13 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertRetrieveParams && alertId == other.alertId && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
+ return other is AlertRetrieveParams &&
+ alertId == other.alertId &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(alertId, additionalHeaders, additionalQueryParams) /* spotless:on */
+ override fun hashCode(): Int = Objects.hash(alertId, additionalHeaders, additionalQueryParams)
override fun toString() =
"AlertRetrieveParams{alertId=$alertId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertUpdateParams.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertUpdateParams.kt
index 9c3d35214..015670473 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertUpdateParams.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AlertUpdateParams.kt
@@ -269,6 +269,7 @@ private constructor(
override fun _queryParams(): QueryParams = additionalQueryParams
class Body
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val thresholds: JsonField>,
private val additionalProperties: MutableMap,
@@ -430,12 +431,12 @@ private constructor(
return true
}
- return /* spotless:off */ other is Body && thresholds == other.thresholds && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Body &&
+ thresholds == other.thresholds &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
private val hashCode: Int by lazy { Objects.hash(thresholds, additionalProperties) }
- /* spotless:on */
override fun hashCode(): Int = hashCode
@@ -448,10 +449,15 @@ private constructor(
return true
}
- return /* spotless:off */ other is AlertUpdateParams && alertConfigurationId == other.alertConfigurationId && body == other.body && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
+ return other is AlertUpdateParams &&
+ alertConfigurationId == other.alertConfigurationId &&
+ body == other.body &&
+ additionalHeaders == other.additionalHeaders &&
+ additionalQueryParams == other.additionalQueryParams
}
- override fun hashCode(): Int = /* spotless:off */ Objects.hash(alertConfigurationId, body, additionalHeaders, additionalQueryParams) /* spotless:on */
+ override fun hashCode(): Int =
+ Objects.hash(alertConfigurationId, body, additionalHeaders, additionalQueryParams)
override fun toString() =
"AlertUpdateParams{alertConfigurationId=$alertConfigurationId, body=$body, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Allocation.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Allocation.kt
index 4cea3f8d3..ae54b8ec3 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Allocation.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/Allocation.kt
@@ -6,20 +6,25 @@ 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.withorb.api.core.Enum
import com.withorb.api.core.ExcludeMissing
import com.withorb.api.core.JsonField
import com.withorb.api.core.JsonMissing
import com.withorb.api.core.JsonValue
+import com.withorb.api.core.checkKnown
import com.withorb.api.core.checkRequired
+import com.withorb.api.core.toImmutable
import com.withorb.api.errors.OrbInvalidDataException
import java.util.Collections
import java.util.Objects
class Allocation
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val allowsRollover: JsonField,
private val currency: JsonField,
private val customExpiration: JsonField,
+ private val filters: JsonField>,
private val additionalProperties: MutableMap,
) {
@@ -32,7 +37,8 @@ private constructor(
@JsonProperty("custom_expiration")
@ExcludeMissing
customExpiration: JsonField = JsonMissing.of(),
- ) : this(allowsRollover, currency, customExpiration, mutableMapOf())
+ @JsonProperty("filters") @ExcludeMissing filters: JsonField> = JsonMissing.of(),
+ ) : this(allowsRollover, currency, customExpiration, filters, mutableMapOf())
/**
* @throws OrbInvalidDataException if the JSON field has an unexpected type or is unexpectedly
@@ -52,6 +58,12 @@ private constructor(
*/
fun customExpiration(): CustomExpiration? = customExpiration.getNullable("custom_expiration")
+ /**
+ * @throws OrbInvalidDataException if the JSON field has an unexpected type (e.g. if the server
+ * responded with an unexpected value).
+ */
+ fun filters(): List? = filters.getNullable("filters")
+
/**
* Returns the raw JSON value of [allowsRollover].
*
@@ -78,6 +90,13 @@ private constructor(
@ExcludeMissing
fun _customExpiration(): JsonField = customExpiration
+ /**
+ * Returns the raw JSON value of [filters].
+ *
+ * Unlike [filters], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("filters") @ExcludeMissing fun _filters(): JsonField> = filters
+
@JsonAnySetter
private fun putAdditionalProperty(key: String, value: JsonValue) {
additionalProperties.put(key, value)
@@ -111,12 +130,14 @@ private constructor(
private var allowsRollover: JsonField? = null
private var currency: JsonField? = null
private var customExpiration: JsonField? = null
+ private var filters: JsonField>? = null
private var additionalProperties: MutableMap = mutableMapOf()
internal fun from(allocation: Allocation) = apply {
allowsRollover = allocation.allowsRollover
currency = allocation.currency
customExpiration = allocation.customExpiration
+ filters = allocation.filters.map { it.toMutableList() }
additionalProperties = allocation.additionalProperties.toMutableMap()
}
@@ -157,6 +178,31 @@ private constructor(
this.customExpiration = customExpiration
}
+ fun filters(filters: List) = filters(JsonField.of(filters))
+
+ /**
+ * Sets [Builder.filters] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.filters] with a well-typed `List` value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun filters(filters: JsonField>) = apply {
+ this.filters = filters.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [Filter] to [filters].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addFilter(filter: Filter) = apply {
+ filters =
+ (filters ?: JsonField.of(mutableListOf())).also {
+ checkKnown("filters", it).add(filter)
+ }
+ }
+
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
putAllAdditionalProperties(additionalProperties)
@@ -195,6 +241,7 @@ private constructor(
checkRequired("allowsRollover", allowsRollover),
checkRequired("currency", currency),
checkRequired("customExpiration", customExpiration),
+ (filters ?: JsonMissing.of()).map { it.toImmutable() },
additionalProperties.toMutableMap(),
)
}
@@ -209,6 +256,7 @@ private constructor(
allowsRollover()
currency()
customExpiration()?.validate()
+ filters()?.forEach { it.validate() }
validated = true
}
@@ -228,22 +276,556 @@ private constructor(
internal fun validity(): Int =
(if (allowsRollover.asKnown() == null) 0 else 1) +
(if (currency.asKnown() == null) 0 else 1) +
- (customExpiration.asKnown()?.validity() ?: 0)
+ (customExpiration.asKnown()?.validity() ?: 0) +
+ (filters.asKnown()?.sumOf { it.validity().toInt() } ?: 0)
+
+ class Filter
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
+ private constructor(
+ private val field: JsonField,
+ private val operator: JsonField,
+ private val values: JsonField>,
+ private val additionalProperties: MutableMap,
+ ) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("field") @ExcludeMissing field: JsonField = JsonMissing.of(),
+ @JsonProperty("operator")
+ @ExcludeMissing
+ operator: JsonField = JsonMissing.of(),
+ @JsonProperty("values")
+ @ExcludeMissing
+ values: JsonField> = JsonMissing.of(),
+ ) : this(field, operator, values, mutableMapOf())
+
+ /**
+ * The property of the price to filter on.
+ *
+ * @throws OrbInvalidDataException 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 field(): Field = field.getRequired("field")
+
+ /**
+ * Should prices that match the filter be included or excluded.
+ *
+ * @throws OrbInvalidDataException 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 operator(): Operator = operator.getRequired("operator")
+
+ /**
+ * The IDs or values that match this filter.
+ *
+ * @throws OrbInvalidDataException 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 values(): List = values.getRequired("values")
+
+ /**
+ * Returns the raw JSON value of [field].
+ *
+ * Unlike [field], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("field") @ExcludeMissing fun _field(): JsonField = field
+
+ /**
+ * Returns the raw JSON value of [operator].
+ *
+ * Unlike [operator], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("operator") @ExcludeMissing fun _operator(): JsonField = operator
+
+ /**
+ * Returns the raw JSON value of [values].
+ *
+ * Unlike [values], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("values") @ExcludeMissing fun _values(): JsonField> = values
+
+ @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 [Filter].
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .field()
+ * .operator()
+ * .values()
+ * ```
+ */
+ fun builder() = Builder()
+ }
+
+ /** A builder for [Filter]. */
+ class Builder internal constructor() {
+
+ private var field: JsonField? = null
+ private var operator: JsonField? = null
+ private var values: JsonField>? = null
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ internal fun from(filter: Filter) = apply {
+ field = filter.field
+ operator = filter.operator
+ values = filter.values.map { it.toMutableList() }
+ additionalProperties = filter.additionalProperties.toMutableMap()
+ }
+
+ /** The property of the price to filter on. */
+ fun field(field: Field) = field(JsonField.of(field))
+
+ /**
+ * Sets [Builder.field] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.field] with a well-typed [Field] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun field(field: JsonField) = apply { this.field = field }
+
+ /** Should prices that match the filter be included or excluded. */
+ fun operator(operator: Operator) = operator(JsonField.of(operator))
+
+ /**
+ * Sets [Builder.operator] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.operator] with a well-typed [Operator] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun operator(operator: JsonField) = apply { this.operator = operator }
+
+ /** The IDs or values that match this filter. */
+ fun values(values: List) = values(JsonField.of(values))
+
+ /**
+ * Sets [Builder.values] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.values] with a well-typed `List` value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun values(values: JsonField>) = apply {
+ this.values = values.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [String] to [values].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addValue(value: String) = apply {
+ values =
+ (values ?: JsonField.of(mutableListOf())).also {
+ checkKnown("values", it).add(value)
+ }
+ }
+
+ 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 [Filter].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .field()
+ * .operator()
+ * .values()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): Filter =
+ Filter(
+ checkRequired("field", field),
+ checkRequired("operator", operator),
+ checkRequired("values", values).map { it.toImmutable() },
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Filter = apply {
+ if (validated) {
+ return@apply
+ }
+
+ field().validate()
+ operator().validate()
+ values()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ internal fun validity(): Int =
+ (field.asKnown()?.validity() ?: 0) +
+ (operator.asKnown()?.validity() ?: 0) +
+ (values.asKnown()?.size ?: 0)
+
+ /** The property of the price to filter on. */
+ class Field @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 {
+
+ val PRICE_ID = of("price_id")
+
+ val ITEM_ID = of("item_id")
+
+ val PRICE_TYPE = of("price_type")
+
+ val CURRENCY = of("currency")
+
+ val PRICING_UNIT_ID = of("pricing_unit_id")
+
+ fun of(value: String) = Field(JsonField.of(value))
+ }
+
+ /** An enum containing [Field]'s known values. */
+ enum class Known {
+ PRICE_ID,
+ ITEM_ID,
+ PRICE_TYPE,
+ CURRENCY,
+ PRICING_UNIT_ID,
+ }
+
+ /**
+ * An enum containing [Field]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Field] 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 {
+ PRICE_ID,
+ ITEM_ID,
+ PRICE_TYPE,
+ CURRENCY,
+ PRICING_UNIT_ID,
+ /**
+ * An enum member indicating that [Field] 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) {
+ PRICE_ID -> Value.PRICE_ID
+ ITEM_ID -> Value.ITEM_ID
+ PRICE_TYPE -> Value.PRICE_TYPE
+ CURRENCY -> Value.CURRENCY
+ PRICING_UNIT_ID -> Value.PRICING_UNIT_ID
+ 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 OrbInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ PRICE_ID -> Known.PRICE_ID
+ ITEM_ID -> Known.ITEM_ID
+ PRICE_TYPE -> Known.PRICE_TYPE
+ CURRENCY -> Known.CURRENCY
+ PRICING_UNIT_ID -> Known.PRICING_UNIT_ID
+ else -> throw OrbInvalidDataException("Unknown Field: $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 OrbInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw OrbInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Field = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ 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 Field && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ /** Should prices that match the filter be included or excluded. */
+ class Operator @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 {
+
+ val INCLUDES = of("includes")
+
+ val EXCLUDES = of("excludes")
+
+ fun of(value: String) = Operator(JsonField.of(value))
+ }
+
+ /** An enum containing [Operator]'s known values. */
+ enum class Known {
+ INCLUDES,
+ EXCLUDES,
+ }
+
+ /**
+ * An enum containing [Operator]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Operator] 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 {
+ INCLUDES,
+ EXCLUDES,
+ /**
+ * An enum member indicating that [Operator] 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) {
+ INCLUDES -> Value.INCLUDES
+ EXCLUDES -> Value.EXCLUDES
+ 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 OrbInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ INCLUDES -> Known.INCLUDES
+ EXCLUDES -> Known.EXCLUDES
+ else -> throw OrbInvalidDataException("Unknown Operator: $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 OrbInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw OrbInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Operator = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ 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 Operator && 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 Filter &&
+ field == other.field &&
+ operator == other.operator &&
+ values == other.values &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(field, operator, values, additionalProperties)
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "Filter{field=$field, operator=$operator, values=$values, additionalProperties=$additionalProperties}"
+ }
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
- return /* spotless:off */ other is Allocation && allowsRollover == other.allowsRollover && currency == other.currency && customExpiration == other.customExpiration && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Allocation &&
+ allowsRollover == other.allowsRollover &&
+ currency == other.currency &&
+ customExpiration == other.customExpiration &&
+ filters == other.filters &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(allowsRollover, currency, customExpiration, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(allowsRollover, currency, customExpiration, filters, additionalProperties)
+ }
override fun hashCode(): Int = hashCode
override fun toString() =
- "Allocation{allowsRollover=$allowsRollover, currency=$currency, customExpiration=$customExpiration, additionalProperties=$additionalProperties}"
+ "Allocation{allowsRollover=$allowsRollover, currency=$currency, customExpiration=$customExpiration, filters=$filters, additionalProperties=$additionalProperties}"
}
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmendmentLedgerEntry.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmendmentLedgerEntry.kt
index 518f4f6d7..bf3f011b5 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmendmentLedgerEntry.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmendmentLedgerEntry.kt
@@ -19,6 +19,7 @@ import java.util.Collections
import java.util.Objects
class AmendmentLedgerEntry
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val id: JsonField,
private val amount: JsonField,
@@ -735,7 +736,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is EntryStatus && value == other.value /* spotless:on */
+ return other is EntryStatus && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -855,7 +856,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is EntryType && value == other.value /* spotless:on */
+ return other is EntryType && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -955,12 +956,10 @@ private constructor(
return true
}
- return /* spotless:off */ other is Metadata && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is Metadata && additionalProperties == other.additionalProperties
}
- /* spotless:off */
private val hashCode: Int by lazy { Objects.hash(additionalProperties) }
- /* spotless:on */
override fun hashCode(): Int = hashCode
@@ -972,12 +971,41 @@ private constructor(
return true
}
- return /* spotless:off */ other is AmendmentLedgerEntry && id == other.id && amount == other.amount && createdAt == other.createdAt && creditBlock == other.creditBlock && currency == other.currency && customer == other.customer && description == other.description && endingBalance == other.endingBalance && entryStatus == other.entryStatus && entryType == other.entryType && ledgerSequenceNumber == other.ledgerSequenceNumber && metadata == other.metadata && startingBalance == other.startingBalance && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AmendmentLedgerEntry &&
+ id == other.id &&
+ amount == other.amount &&
+ createdAt == other.createdAt &&
+ creditBlock == other.creditBlock &&
+ currency == other.currency &&
+ customer == other.customer &&
+ description == other.description &&
+ endingBalance == other.endingBalance &&
+ entryStatus == other.entryStatus &&
+ entryType == other.entryType &&
+ ledgerSequenceNumber == other.ledgerSequenceNumber &&
+ metadata == other.metadata &&
+ startingBalance == other.startingBalance &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(id, amount, createdAt, creditBlock, currency, customer, description, endingBalance, entryStatus, entryType, ledgerSequenceNumber, metadata, startingBalance, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ id,
+ amount,
+ createdAt,
+ creditBlock,
+ currency,
+ customer,
+ description,
+ endingBalance,
+ entryStatus,
+ entryType,
+ ledgerSequenceNumber,
+ metadata,
+ startingBalance,
+ additionalProperties,
+ )
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscount.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscount.kt
index 6fbf2c402..5bec912af 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscount.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscount.kt
@@ -19,11 +19,12 @@ import java.util.Collections
import java.util.Objects
class AmountDiscount
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val amountDiscount: JsonField,
private val discountType: JsonField,
private val appliesToPriceIds: JsonField>,
- private val filters: JsonField>,
+ private val filters: JsonField>,
private val reason: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -41,7 +42,7 @@ private constructor(
appliesToPriceIds: JsonField> = JsonMissing.of(),
@JsonProperty("filters")
@ExcludeMissing
- filters: JsonField> = JsonMissing.of(),
+ filters: JsonField> = JsonMissing.of(),
@JsonProperty("reason") @ExcludeMissing reason: JsonField = JsonMissing.of(),
) : this(amountDiscount, discountType, appliesToPriceIds, filters, reason, mutableMapOf())
@@ -74,7 +75,7 @@ private constructor(
* @throws OrbInvalidDataException if the JSON field has an unexpected type (e.g. if the server
* responded with an unexpected value).
*/
- fun filters(): List? = filters.getNullable("filters")
+ fun filters(): List? = filters.getNullable("filters")
/**
* @throws OrbInvalidDataException if the JSON field has an unexpected type (e.g. if the server
@@ -115,9 +116,7 @@ private constructor(
*
* Unlike [filters], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("filters")
- @ExcludeMissing
- fun _filters(): JsonField> = filters
+ @JsonProperty("filters") @ExcludeMissing fun _filters(): JsonField> = filters
/**
* Returns the raw JSON value of [reason].
@@ -158,7 +157,7 @@ private constructor(
private var amountDiscount: JsonField? = null
private var discountType: JsonField? = null
private var appliesToPriceIds: JsonField>? = null
- private var filters: JsonField>? = null
+ private var filters: JsonField>? = null
private var reason: JsonField = JsonMissing.of()
private var additionalProperties: MutableMap = mutableMapOf()
@@ -229,25 +228,25 @@ private constructor(
}
/** The filters that determine which prices to apply this discount to. */
- fun filters(filters: List?) = filters(JsonField.ofNullable(filters))
+ fun filters(filters: List?) = filters(JsonField.ofNullable(filters))
/**
* Sets [Builder.filters] to an arbitrary JSON value.
*
- * You should usually call [Builder.filters] with a well-typed `List`
- * value instead. This method is primarily for setting the field to an undocumented or not
- * yet supported value.
+ * You should usually call [Builder.filters] with a well-typed `List` value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
*/
- fun filters(filters: JsonField>) = apply {
+ fun filters(filters: JsonField>) = apply {
this.filters = filters.map { it.toMutableList() }
}
/**
- * Adds a single [TransformPriceFilter] to [filters].
+ * Adds a single [Filter] to [filters].
*
* @throws IllegalStateException if the field was previously set to a non-list.
*/
- fun addFilter(filter: TransformPriceFilter) = apply {
+ fun addFilter(filter: Filter) = apply {
filters =
(filters ?: JsonField.of(mutableListOf())).also {
checkKnown("filters", it).add(filter)
@@ -455,7 +454,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is DiscountType && value == other.value /* spotless:on */
+ return other is DiscountType && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -463,17 +462,558 @@ private constructor(
override fun toString() = value.toString()
}
+ class Filter
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
+ private constructor(
+ private val field: JsonField,
+ private val operator: JsonField,
+ private val values: JsonField>,
+ private val additionalProperties: MutableMap,
+ ) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("field") @ExcludeMissing field: JsonField = JsonMissing.of(),
+ @JsonProperty("operator")
+ @ExcludeMissing
+ operator: JsonField = JsonMissing.of(),
+ @JsonProperty("values")
+ @ExcludeMissing
+ values: JsonField> = JsonMissing.of(),
+ ) : this(field, operator, values, mutableMapOf())
+
+ /**
+ * The property of the price to filter on.
+ *
+ * @throws OrbInvalidDataException 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 field(): Field = field.getRequired("field")
+
+ /**
+ * Should prices that match the filter be included or excluded.
+ *
+ * @throws OrbInvalidDataException 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 operator(): Operator = operator.getRequired("operator")
+
+ /**
+ * The IDs or values that match this filter.
+ *
+ * @throws OrbInvalidDataException 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 values(): List = values.getRequired("values")
+
+ /**
+ * Returns the raw JSON value of [field].
+ *
+ * Unlike [field], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("field") @ExcludeMissing fun _field(): JsonField = field
+
+ /**
+ * Returns the raw JSON value of [operator].
+ *
+ * Unlike [operator], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("operator") @ExcludeMissing fun _operator(): JsonField = operator
+
+ /**
+ * Returns the raw JSON value of [values].
+ *
+ * Unlike [values], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("values") @ExcludeMissing fun _values(): JsonField> = values
+
+ @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 [Filter].
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .field()
+ * .operator()
+ * .values()
+ * ```
+ */
+ fun builder() = Builder()
+ }
+
+ /** A builder for [Filter]. */
+ class Builder internal constructor() {
+
+ private var field: JsonField? = null
+ private var operator: JsonField? = null
+ private var values: JsonField>? = null
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ internal fun from(filter: Filter) = apply {
+ field = filter.field
+ operator = filter.operator
+ values = filter.values.map { it.toMutableList() }
+ additionalProperties = filter.additionalProperties.toMutableMap()
+ }
+
+ /** The property of the price to filter on. */
+ fun field(field: Field) = field(JsonField.of(field))
+
+ /**
+ * Sets [Builder.field] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.field] with a well-typed [Field] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun field(field: JsonField) = apply { this.field = field }
+
+ /** Should prices that match the filter be included or excluded. */
+ fun operator(operator: Operator) = operator(JsonField.of(operator))
+
+ /**
+ * Sets [Builder.operator] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.operator] with a well-typed [Operator] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun operator(operator: JsonField) = apply { this.operator = operator }
+
+ /** The IDs or values that match this filter. */
+ fun values(values: List) = values(JsonField.of(values))
+
+ /**
+ * Sets [Builder.values] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.values] with a well-typed `List` value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun values(values: JsonField>) = apply {
+ this.values = values.map { it.toMutableList() }
+ }
+
+ /**
+ * Adds a single [String] to [values].
+ *
+ * @throws IllegalStateException if the field was previously set to a non-list.
+ */
+ fun addValue(value: String) = apply {
+ values =
+ (values ?: JsonField.of(mutableListOf())).also {
+ checkKnown("values", it).add(value)
+ }
+ }
+
+ 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 [Filter].
+ *
+ * Further updates to this [Builder] will not mutate the returned instance.
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .field()
+ * .operator()
+ * .values()
+ * ```
+ *
+ * @throws IllegalStateException if any required field is unset.
+ */
+ fun build(): Filter =
+ Filter(
+ checkRequired("field", field),
+ checkRequired("operator", operator),
+ checkRequired("values", values).map { it.toImmutable() },
+ additionalProperties.toMutableMap(),
+ )
+ }
+
+ private var validated: Boolean = false
+
+ fun validate(): Filter = apply {
+ if (validated) {
+ return@apply
+ }
+
+ field().validate()
+ operator().validate()
+ values()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ internal fun validity(): Int =
+ (field.asKnown()?.validity() ?: 0) +
+ (operator.asKnown()?.validity() ?: 0) +
+ (values.asKnown()?.size ?: 0)
+
+ /** The property of the price to filter on. */
+ class Field @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 {
+
+ val PRICE_ID = of("price_id")
+
+ val ITEM_ID = of("item_id")
+
+ val PRICE_TYPE = of("price_type")
+
+ val CURRENCY = of("currency")
+
+ val PRICING_UNIT_ID = of("pricing_unit_id")
+
+ fun of(value: String) = Field(JsonField.of(value))
+ }
+
+ /** An enum containing [Field]'s known values. */
+ enum class Known {
+ PRICE_ID,
+ ITEM_ID,
+ PRICE_TYPE,
+ CURRENCY,
+ PRICING_UNIT_ID,
+ }
+
+ /**
+ * An enum containing [Field]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Field] 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 {
+ PRICE_ID,
+ ITEM_ID,
+ PRICE_TYPE,
+ CURRENCY,
+ PRICING_UNIT_ID,
+ /**
+ * An enum member indicating that [Field] 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) {
+ PRICE_ID -> Value.PRICE_ID
+ ITEM_ID -> Value.ITEM_ID
+ PRICE_TYPE -> Value.PRICE_TYPE
+ CURRENCY -> Value.CURRENCY
+ PRICING_UNIT_ID -> Value.PRICING_UNIT_ID
+ 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 OrbInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ PRICE_ID -> Known.PRICE_ID
+ ITEM_ID -> Known.ITEM_ID
+ PRICE_TYPE -> Known.PRICE_TYPE
+ CURRENCY -> Known.CURRENCY
+ PRICING_UNIT_ID -> Known.PRICING_UNIT_ID
+ else -> throw OrbInvalidDataException("Unknown Field: $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 OrbInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw OrbInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Field = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ 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 Field && value == other.value
+ }
+
+ override fun hashCode() = value.hashCode()
+
+ override fun toString() = value.toString()
+ }
+
+ /** Should prices that match the filter be included or excluded. */
+ class Operator @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 {
+
+ val INCLUDES = of("includes")
+
+ val EXCLUDES = of("excludes")
+
+ fun of(value: String) = Operator(JsonField.of(value))
+ }
+
+ /** An enum containing [Operator]'s known values. */
+ enum class Known {
+ INCLUDES,
+ EXCLUDES,
+ }
+
+ /**
+ * An enum containing [Operator]'s known values, as well as an [_UNKNOWN] member.
+ *
+ * An instance of [Operator] 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 {
+ INCLUDES,
+ EXCLUDES,
+ /**
+ * An enum member indicating that [Operator] 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) {
+ INCLUDES -> Value.INCLUDES
+ EXCLUDES -> Value.EXCLUDES
+ 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 OrbInvalidDataException if this class instance's value is a not a known
+ * member.
+ */
+ fun known(): Known =
+ when (this) {
+ INCLUDES -> Known.INCLUDES
+ EXCLUDES -> Known.EXCLUDES
+ else -> throw OrbInvalidDataException("Unknown Operator: $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 OrbInvalidDataException if this class instance's value does not have the
+ * expected primitive type.
+ */
+ fun asString(): String =
+ _value().asString() ?: throw OrbInvalidDataException("Value is not a String")
+
+ private var validated: Boolean = false
+
+ fun validate(): Operator = apply {
+ if (validated) {
+ return@apply
+ }
+
+ known()
+ validated = true
+ }
+
+ fun isValid(): Boolean =
+ try {
+ validate()
+ true
+ } catch (e: OrbInvalidDataException) {
+ false
+ }
+
+ /**
+ * Returns a score indicating how many valid values are contained in this object
+ * recursively.
+ *
+ * Used for best match union deserialization.
+ */
+ 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 Operator && 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 Filter &&
+ field == other.field &&
+ operator == other.operator &&
+ values == other.values &&
+ additionalProperties == other.additionalProperties
+ }
+
+ private val hashCode: Int by lazy {
+ Objects.hash(field, operator, values, additionalProperties)
+ }
+
+ override fun hashCode(): Int = hashCode
+
+ override fun toString() =
+ "Filter{field=$field, operator=$operator, values=$values, additionalProperties=$additionalProperties}"
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) {
return true
}
- return /* spotless:off */ other is AmountDiscount && amountDiscount == other.amountDiscount && discountType == other.discountType && appliesToPriceIds == other.appliesToPriceIds && filters == other.filters && reason == other.reason && additionalProperties == other.additionalProperties /* spotless:on */
+ return other is AmountDiscount &&
+ amountDiscount == other.amountDiscount &&
+ discountType == other.discountType &&
+ appliesToPriceIds == other.appliesToPriceIds &&
+ filters == other.filters &&
+ reason == other.reason &&
+ additionalProperties == other.additionalProperties
}
- /* spotless:off */
- private val hashCode: Int by lazy { Objects.hash(amountDiscount, discountType, appliesToPriceIds, filters, reason, additionalProperties) }
- /* spotless:on */
+ private val hashCode: Int by lazy {
+ Objects.hash(
+ amountDiscount,
+ discountType,
+ appliesToPriceIds,
+ filters,
+ reason,
+ additionalProperties,
+ )
+ }
override fun hashCode(): Int = hashCode
diff --git a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscountInterval.kt b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscountInterval.kt
index 87da187c2..40d6c920e 100644
--- a/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscountInterval.kt
+++ b/orb-kotlin-core/src/main/kotlin/com/withorb/api/models/AmountDiscountInterval.kt
@@ -20,12 +20,13 @@ import java.util.Collections
import java.util.Objects
class AmountDiscountInterval
+@JsonCreator(mode = JsonCreator.Mode.DISABLED)
private constructor(
private val amountDiscount: JsonField,
private val appliesToPriceIntervalIds: JsonField>,
private val discountType: JsonField,
private val endDate: JsonField,
- private val filters: JsonField>,
+ private val filters: JsonField>,
private val startDate: JsonField,
private val additionalProperties: MutableMap,
) {
@@ -46,7 +47,7 @@ private constructor(
endDate: JsonField = JsonMissing.of(),
@JsonProperty("filters")
@ExcludeMissing
- filters: JsonField> = JsonMissing.of(),
+ filters: JsonField> = JsonMissing.of(),
@JsonProperty("start_date")
@ExcludeMissing
startDate: JsonField = JsonMissing.of(),
@@ -97,7 +98,7 @@ private constructor(
* @throws OrbInvalidDataException 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 filters(): List = filters.getRequired("filters")
+ fun filters(): List = filters.getRequired("filters")
/**
* The start date of the discount interval.
@@ -147,9 +148,7 @@ private constructor(
*
* Unlike [filters], this method doesn't throw if the JSON field has an unexpected type.
*/
- @JsonProperty("filters")
- @ExcludeMissing
- fun _filters(): JsonField> = filters
+ @JsonProperty("filters") @ExcludeMissing fun _filters(): JsonField> = filters
/**
* Returns the raw JSON value of [startDate].
@@ -197,7 +196,7 @@ private constructor(
private var appliesToPriceIntervalIds: JsonField>? = null
private var discountType: JsonField? = null
private var endDate: JsonField? = null
- private var filters: JsonField>? = null
+ private var filters: JsonField>? = null
private var startDate: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
@@ -279,25 +278,25 @@ private constructor(
fun endDate(endDate: JsonField) = apply { this.endDate = endDate }
/** The filters that determine which prices this discount interval applies to. */
- fun filters(filters: List) = filters(JsonField.of(filters))
+ fun filters(filters: List) = filters(JsonField.of(filters))
/**
* Sets [Builder.filters] to an arbitrary JSON value.
*
- * You should usually call [Builder.filters] with a well-typed `List`
- * value instead. This method is primarily for setting the field to an undocumented or not
- * yet supported value.
+ * You should usually call [Builder.filters] with a well-typed `List` value instead.
+ * This method is primarily for setting the field to an undocumented or not yet supported
+ * value.
*/
- fun filters(filters: JsonField>) = apply {
+ fun filters(filters: JsonField>) = apply {
this.filters = filters.map { it.toMutableList() }
}
/**
- * Adds a single [TransformPriceFilter] to [filters].
+ * Adds a single [Filter] to [filters].
*
* @throws IllegalStateException if the field was previously set to a non-list.
*/
- fun addFilter(filter: TransformPriceFilter) = apply {
+ fun addFilter(filter: Filter) = apply {
filters =
(filters ?: JsonField.of(mutableListOf())).also {
checkKnown("filters", it).add(filter)
@@ -516,7 +515,7 @@ private constructor(
return true
}
- return /* spotless:off */ other is DiscountType && value == other.value /* spotless:on */
+ return other is DiscountType && value == other.value
}
override fun hashCode() = value.hashCode()
@@ -524,17 +523,560 @@ private constructor(
override fun toString() = value.toString()
}
+ class Filter
+ @JsonCreator(mode = JsonCreator.Mode.DISABLED)
+ private constructor(
+ private val field: JsonField,
+ private val operator: JsonField,
+ private val values: JsonField>,
+ private val additionalProperties: MutableMap,
+ ) {
+
+ @JsonCreator
+ private constructor(
+ @JsonProperty("field") @ExcludeMissing field: JsonField = JsonMissing.of(),
+ @JsonProperty("operator")
+ @ExcludeMissing
+ operator: JsonField = JsonMissing.of(),
+ @JsonProperty("values")
+ @ExcludeMissing
+ values: JsonField> = JsonMissing.of(),
+ ) : this(field, operator, values, mutableMapOf())
+
+ /**
+ * The property of the price to filter on.
+ *
+ * @throws OrbInvalidDataException 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 field(): Field = field.getRequired("field")
+
+ /**
+ * Should prices that match the filter be included or excluded.
+ *
+ * @throws OrbInvalidDataException 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 operator(): Operator = operator.getRequired("operator")
+
+ /**
+ * The IDs or values that match this filter.
+ *
+ * @throws OrbInvalidDataException 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 values(): List = values.getRequired("values")
+
+ /**
+ * Returns the raw JSON value of [field].
+ *
+ * Unlike [field], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("field") @ExcludeMissing fun _field(): JsonField = field
+
+ /**
+ * Returns the raw JSON value of [operator].
+ *
+ * Unlike [operator], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("operator") @ExcludeMissing fun _operator(): JsonField = operator
+
+ /**
+ * Returns the raw JSON value of [values].
+ *
+ * Unlike [values], this method doesn't throw if the JSON field has an unexpected type.
+ */
+ @JsonProperty("values") @ExcludeMissing fun _values(): JsonField> = values
+
+ @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 [Filter].
+ *
+ * The following fields are required:
+ * ```kotlin
+ * .field()
+ * .operator()
+ * .values()
+ * ```
+ */
+ fun builder() = Builder()
+ }
+
+ /** A builder for [Filter]. */
+ class Builder internal constructor() {
+
+ private var field: JsonField? = null
+ private var operator: JsonField? = null
+ private var values: JsonField>? = null
+ private var additionalProperties: MutableMap = mutableMapOf()
+
+ internal fun from(filter: Filter) = apply {
+ field = filter.field
+ operator = filter.operator
+ values = filter.values.map { it.toMutableList() }
+ additionalProperties = filter.additionalProperties.toMutableMap()
+ }
+
+ /** The property of the price to filter on. */
+ fun field(field: Field) = field(JsonField.of(field))
+
+ /**
+ * Sets [Builder.field] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.field] with a well-typed [Field] value instead. This
+ * method is primarily for setting the field to an undocumented or not yet supported
+ * value.
+ */
+ fun field(field: JsonField) = apply { this.field = field }
+
+ /** Should prices that match the filter be included or excluded. */
+ fun operator(operator: Operator) = operator(JsonField.of(operator))
+
+ /**
+ * Sets [Builder.operator] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.operator] with a well-typed [Operator] value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun operator(operator: JsonField) = apply { this.operator = operator }
+
+ /** The IDs or values that match this filter. */
+ fun values(values: List) = values(JsonField.of(values))
+
+ /**
+ * Sets [Builder.values] to an arbitrary JSON value.
+ *
+ * You should usually call [Builder.values] with a well-typed `List` value
+ * instead. This method is primarily for setting the field to an undocumented or not yet
+ * supported value.
+ */
+ fun values(values: JsonField