diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dec625ee6..fcb9e6804 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,14 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' @@ -17,7 +19,7 @@ jobs: timeout-minutes: 15 name: lint runs-on: ${{ github.repository == 'stainless-sdks/finch-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 @@ -44,7 +46,7 @@ jobs: contents: read id-token: write runs-on: ${{ github.repository == 'stainless-sdks/finch-java' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 @@ -65,14 +67,18 @@ jobs: run: ./scripts/build - name: Get GitHub OIDC Token - if: github.repository == 'stainless-sdks/finch-java' + if: |- + github.repository == 'stainless-sdks/finch-java' && + !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc uses: actions/github-script@v8 with: script: core.setOutput('github_token', await core.getIDToken()); - name: Build and upload Maven artifacts - if: github.repository == 'stainless-sdks/finch-java' + if: |- + github.repository == 'stainless-sdks/finch-java' && + !startsWith(github.ref, 'refs/heads/stl/') env: URL: https://pkg.stainless.com/s AUTH: ${{ steps.github-oidc.outputs.github_token }} diff --git a/.gitignore b/.gitignore index b1346e6d1..90b85e944 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log .gradle .idea .kotlin diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8e11baaee..01f6bba7b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.6.0" + ".": "7.7.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 5157ee799..8dd833a1d 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 45 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch%2Ffinch-46f433f34d440aa1dfcc48cc8d822c598571b68be2f723ec99e1b4fba6c13b1e.yml -openapi_spec_hash: 5b5cd728776723ac773900f7e8a32c05 -config_hash: ccdf6a5b4aaa2a0897c89ac8685d8eb0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/finch/finch-c8a0d5eca390ea3ab6e8b5b7d9b46d9a22e34d81aeab444c8ce1b5a94eba0028.yml +openapi_spec_hash: e261a3289242d3ad52542f1491a903ee +config_hash: 429708b67ee9e80003db82611677296c diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cf9e908a..048a7fe03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,77 @@ # Changelog +## 7.7.0 (2026-05-07) + +Full Changelog: [v7.6.0...v7.7.0](https://github.com/Finch-API/finch-api-java/compare/v7.6.0...v7.7.0) + +### Features + +* **api:** api update ([7428d26](https://github.com/Finch-API/finch-api-java/commit/7428d26b5ce8d48cc778572db6d00ea611959210)) +* **api:** api update ([e79d0da](https://github.com/Finch-API/finch-api-java/commit/e79d0da99c2159e1f123aa35f1721305dd81947a)) +* **api:** api update ([9a22d87](https://github.com/Finch-API/finch-api-java/commit/9a22d87cee43b9e72021f9c0f290135fdc5b0d88)) +* **api:** api update ([e0941b9](https://github.com/Finch-API/finch-api-java/commit/e0941b90677171c959aef86ae567e217f7ee2280)) +* **api:** api update ([b81180a](https://github.com/Finch-API/finch-api-java/commit/b81180a374d0e2d4515bbc7ced304a2155c57970)) +* **api:** change auth to npm to oidc ([22cb9c3](https://github.com/Finch-API/finch-api-java/commit/22cb9c3fec88c8f8613e4333c81acaf1574873b8)) +* **client:** add connection pooling option ([b32cb5e](https://github.com/Finch-API/finch-api-java/commit/b32cb5e30dd6c8c6e095bf12c1a35c7346adc363)) +* **client:** add more convenience service method overloads ([98dfad7](https://github.com/Finch-API/finch-api-java/commit/98dfad72afb87db1f74daf8599ddd1c4ff9b8a12)) +* **client:** improve logging ([45718e3](https://github.com/Finch-API/finch-api-java/commit/45718e35cfb88e46aafec5206b2b925eea6ef2a2)) +* **client:** more robust error parsing ([31c1298](https://github.com/Finch-API/finch-api-java/commit/31c1298070aa84ef57221071726792bc101413fe)) +* **client:** support proxy authentication ([164fca2](https://github.com/Finch-API/finch-api-java/commit/164fca2658a181686fc63bb7217a671355898912)) +* support setting headers via env ([3d5f1bb](https://github.com/Finch-API/finch-api-java/commit/3d5f1bb1b67cff6fc2e6549e554e4a92e6625457)) + + +### Bug Fixes + +* **api:** remove invalid transform config ([8e955cc](https://github.com/Finch-API/finch-api-java/commit/8e955cc8ecb96538951c34e69abcc59542d56730)) +* **client:** allow updating header/query affecting fields in `toBuilder()` ([a2bef27](https://github.com/Finch-API/finch-api-java/commit/a2bef2796c1853918e215e3181d98a8e85f755a0)) +* **client:** incorrect `Retry-After` parsing ([184ead0](https://github.com/Finch-API/finch-api-java/commit/184ead0c155c912e8be8207a200e71b05b9928a6)) +* **docs:** fix mcp installation instructions for remote servers ([2263e95](https://github.com/Finch-API/finch-api-java/commit/2263e9537df43a609878091903108ecbf216ea76)) + + +### Performance Improvements + +* **client:** create one json mapper ([fa5904f](https://github.com/Finch-API/finch-api-java/commit/fa5904fc90f522bc0685f84b0a80396ed6bb8775)) + + +### Chores + +* **api:** minor updates ([517681b](https://github.com/Finch-API/finch-api-java/commit/517681b1ab0f11cfb16e5652597a73734ed94314)) +* **ci:** skip lint on metadata-only changes ([097c2e8](https://github.com/Finch-API/finch-api-java/commit/097c2e82ecee3fc1a290a09fde1e36ef63092224)) +* **ci:** skip uploading artifacts on stainless-internal branches ([511e088](https://github.com/Finch-API/finch-api-java/commit/511e08806a8b10ff2f9f2646ba57c1b126e82929)) +* drop apache dependency ([7e8f6e8](https://github.com/Finch-API/finch-api-java/commit/7e8f6e84b6f957bae05e2f27ba9cf2c46658adcd)) +* **internal:** allow passing args to `./scripts/test` ([5a4b86a](https://github.com/Finch-API/finch-api-java/commit/5a4b86a8afa2a0940f3f751ff4927a9f7c649973)) +* **internal:** codegen related update ([7e59d99](https://github.com/Finch-API/finch-api-java/commit/7e59d9979522714a8346fed5595bc77d593edcb0)) +* **internal:** codegen related update ([4c0d39d](https://github.com/Finch-API/finch-api-java/commit/4c0d39d2d70f43e4b0050c37687b1c90ad307b9f)) +* **internal:** codegen related update ([9390e9d](https://github.com/Finch-API/finch-api-java/commit/9390e9d48290fcf34aff35c5f934f609d2afba06)) +* **internal:** expand imports ([3ee90d0](https://github.com/Finch-API/finch-api-java/commit/3ee90d078b22210aad648c55d3165b8bd225f97a)) +* **internal:** make `OkHttp` constructor internal ([4817a04](https://github.com/Finch-API/finch-api-java/commit/4817a0454a026d3f46018245dcc16bd4f2b850af)) +* **internal:** tweak CI branches ([0a639b6](https://github.com/Finch-API/finch-api-java/commit/0a639b6323addc4b26f69eb0b5538325a84d35fe)) +* **internal:** update `TestServerExtension` comment ([4f87f8c](https://github.com/Finch-API/finch-api-java/commit/4f87f8c75e35f859abd3f6bb53b0f10d9334c43a)) +* **internal:** update gitignore ([c5b3f87](https://github.com/Finch-API/finch-api-java/commit/c5b3f876b0c417adf13f12aac4eb826ff9c1cbb8)) +* **internal:** update multipart form array serialization ([971b625](https://github.com/Finch-API/finch-api-java/commit/971b625704582df1c587ddfbb0134b695b49f486)) +* **internal:** update retry delay tests ([74d13c9](https://github.com/Finch-API/finch-api-java/commit/74d13c9d830887e3bab570b94d54422d695377ba)) +* **internal:** upgrade AssertJ ([1969203](https://github.com/Finch-API/finch-api-java/commit/196920329becccc50491e2daf3ed2dc66df36476)) +* make `Properties` more resilient to `null` ([0019871](https://github.com/Finch-API/finch-api-java/commit/0019871d4b03fc59e37876ed1c6b789a26898d42)) +* redact api-key headers in debug logs ([57fb214](https://github.com/Finch-API/finch-api-java/commit/57fb2149a865153d8a1096e9bd48bfb1cc674378)) +* remove duplicated dokka setup ([a136d65](https://github.com/Finch-API/finch-api-java/commit/a136d65e7fe094dae7c7f21f6cc317736ea84d87)) +* **tests:** bump steady to v0.19.4 ([c5bf4b6](https://github.com/Finch-API/finch-api-java/commit/c5bf4b6b4e233046700aac4d7283255987cbf15f)) +* **tests:** bump steady to v0.19.5 ([c41f85e](https://github.com/Finch-API/finch-api-java/commit/c41f85ec6c0f686db96ad08c13d30f91b6f134b6)) +* **tests:** bump steady to v0.19.6 ([d0696f6](https://github.com/Finch-API/finch-api-java/commit/d0696f688ef503404bd7736173af4619ac3e542e)) +* **tests:** bump steady to v0.19.7 ([cc4b8a7](https://github.com/Finch-API/finch-api-java/commit/cc4b8a7db1e6b38a33b0d1e5e1d0f735dbba566d)) +* **tests:** bump steady to v0.20.1 ([8ea2902](https://github.com/Finch-API/finch-api-java/commit/8ea290264cdc318aea824ee16e99452395fcd182)) +* **tests:** bump steady to v0.20.2 ([62c445f](https://github.com/Finch-API/finch-api-java/commit/62c445f77dc424656b623b5317bd9bee2de78df0)) +* **tests:** bump steady to v0.22.1 ([712b749](https://github.com/Finch-API/finch-api-java/commit/712b749d0a26c855a5b4b2971e1e9f57bf86a2f7)) + + +### Documentation + +* clarify forwards compat behavior ([766609c](https://github.com/Finch-API/finch-api-java/commit/766609c4199c84faf5df9dc24bb583008a4762f3)) + + +### Refactors + +* **tests:** switch from prism to steady ([153f640](https://github.com/Finch-API/finch-api-java/commit/153f6408de564c3ac6e19ef67963f6e11889f289)) + ## 7.6.0 (2026-01-26) Full Changelog: [v7.5.2...v7.6.0](https://github.com/Finch-API/finch-api-java/compare/v7.5.2...v7.6.0) diff --git a/README.md b/README.md index 3b05b9525..12df0aa64 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.tryfinch.api/finch-java)](https://central.sonatype.com/artifact/com.tryfinch.api/finch-java/7.6.0) -[![javadoc](https://javadoc.io/badge2/com.tryfinch.api/finch-java/7.6.0/javadoc.svg)](https://javadoc.io/doc/com.tryfinch.api/finch-java/7.6.0) +[![Maven Central](https://img.shields.io/maven-central/v/com.tryfinch.api/finch-java)](https://central.sonatype.com/artifact/com.tryfinch.api/finch-java/7.7.0) +[![javadoc](https://javadoc.io/badge2/com.tryfinch.api/finch-java/7.7.0/javadoc.svg)](https://javadoc.io/doc/com.tryfinch.api/finch-java/7.7.0) @@ -17,14 +17,14 @@ It is generated with [Stainless](https://www.stainless.com/). Use the Finch MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. -[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40tryfinch%2Ffinch-api-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB0cnlmaW5jaC9maW5jaC1hcGktbWNwIl19) -[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40tryfinch%2Ffinch-api-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40tryfinch%2Ffinch-api-mcp%22%5D%7D) +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40tryfinch%2Ffinch-api-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB0cnlmaW5jaC9maW5jaC1hcGktbWNwIl0sImVudiI6eyJGSU5DSF9BQ0NFU1NfVE9LRU4iOiJNeSBBY2Nlc3MgVG9rZW4iLCJGSU5DSF9DTElFTlRfSUQiOiI0YWIxNWU1MS0xMWFkLTQ5ZjQtYWNhZS1mMzQzYjc3OTQzNzUiLCJGSU5DSF9DTElFTlRfU0VDUkVUIjoiTXkgQ2xpZW50IFNlY3JldCIsIkZJTkNIX1dFQkhPT0tfU0VDUkVUIjoiTXkgV2ViaG9vayBTZWNyZXQifX0) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40tryfinch%2Ffinch-api-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40tryfinch%2Ffinch-api-mcp%22%5D%2C%22env%22%3A%7B%22FINCH_ACCESS_TOKEN%22%3A%22My%20Access%20Token%22%2C%22FINCH_CLIENT_ID%22%3A%224ab15e51-11ad-49f4-acae-f343b7794375%22%2C%22FINCH_CLIENT_SECRET%22%3A%22My%20Client%20Secret%22%2C%22FINCH_WEBHOOK_SECRET%22%3A%22My%20Webhook%20Secret%22%7D%7D) > Note: You may need to set environment variables in your MCP client. -The REST API documentation can be found on [developer.tryfinch.com](https://developer.tryfinch.com/). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.tryfinch.api/finch-java/7.6.0). +The REST API documentation can be found on [developer.tryfinch.com](https://developer.tryfinch.com/). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.tryfinch.api/finch-java/7.7.0). @@ -35,7 +35,7 @@ The REST API documentation can be found on [developer.tryfinch.com](https://deve ### Gradle ```kotlin -implementation("com.tryfinch.api:finch-java:7.6.0") +implementation("com.tryfinch.api:finch-java:7.7.0") ``` ### Maven @@ -44,7 +44,7 @@ implementation("com.tryfinch.api:finch-java:7.6.0") com.tryfinch.api finch-java - 7.6.0 + 7.7.0 ``` @@ -352,8 +352,6 @@ while (true) { ## Logging -The SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor). - Enable logging by setting the `FINCH_LOG` environment variable to `info`: ```sh @@ -366,6 +364,20 @@ Or to `debug` for more verbose logging: export FINCH_LOG=debug ``` +Or configure the client manually using the `logLevel` method: + +```java +import com.tryfinch.api.client.FinchClient; +import com.tryfinch.api.client.okhttp.FinchOkHttpClient; +import com.tryfinch.api.core.LogLevel; + +FinchClient client = FinchOkHttpClient.builder() + .fromEnv() + .logLevel(LogLevel.INFO) + .accessToken("My Access Token") + .build(); +``` + ## Webhook Verification We provide helper methods for verifying that a webhook request came from Finch, and not a malicious third party. @@ -471,6 +483,42 @@ FinchClient client = FinchOkHttpClient.builder() .build(); ``` +If the proxy responds with `407 Proxy Authentication Required`, supply credentials by also configuring `proxyAuthenticator`: + +```java +import com.tryfinch.api.client.FinchClient; +import com.tryfinch.api.client.okhttp.FinchOkHttpClient; +import com.tryfinch.api.core.http.ProxyAuthenticator; + +FinchClient client = FinchOkHttpClient.builder() + .fromEnv() + .proxy(...) + // Or a custom implementation of `ProxyAuthenticator`. + .proxyAuthenticator(ProxyAuthenticator.basic("username", "password")) + .accessToken("My Access Token") + .build(); +``` + +### Connection pooling + +To customize the underlying OkHttp connection pool, configure the client using the `maxIdleConnections` and `keepAliveDuration` methods: + +```java +import com.tryfinch.api.client.FinchClient; +import com.tryfinch.api.client.okhttp.FinchOkHttpClient; +import java.time.Duration; + +FinchClient client = FinchOkHttpClient.builder() + .fromEnv() + // If `maxIdleConnections` is set, then `keepAliveDuration` must be set, and vice versa. + .maxIdleConnections(10) + .keepAliveDuration(Duration.ofMinutes(2)) + .accessToken("My Access Token") + .build(); +``` + +If both options are unset, OkHttp's default connection pool settings are used. + ### HTTPS > [!NOTE] @@ -671,7 +719,9 @@ In rare cases, the API may return a response that doesn't match the expected typ By default, the SDK will not throw an exception in this case. It will throw [`FinchInvalidDataException`](finch-java-core/src/main/kotlin/com/tryfinch/api/errors/FinchInvalidDataException.kt) only if you directly access the property. -If you would prefer to check that the response is completely well-typed upfront, then either call `validate()`: +Validating the response is _not_ forwards compatible with new types from the API for existing fields. + +If you would still prefer to check that the response is completely well-typed upfront, then either call `validate()`: ```java import com.tryfinch.api.models.CreateAccessTokenResponse; diff --git a/build.gradle.kts b/build.gradle.kts index f21b0c405..83fd3d1c8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ repositories { allprojects { group = "com.tryfinch.api" - version = "7.6.0" // x-release-please-version + version = "7.7.0" // x-release-please-version } subprojects { @@ -21,7 +21,6 @@ subprojects { group = "Verification" description = "Verifies all source files are formatted." } - apply(plugin = "org.jetbrains.dokka") } subprojects { diff --git a/buildSrc/src/main/kotlin/finch.java.gradle.kts b/buildSrc/src/main/kotlin/finch.java.gradle.kts index 70fc33f41..8f4f902a6 100644 --- a/buildSrc/src/main/kotlin/finch.java.gradle.kts +++ b/buildSrc/src/main/kotlin/finch.java.gradle.kts @@ -45,7 +45,7 @@ tasks.withType().configureEach { val palantir by configurations.creating dependencies { - palantir("com.palantir.javaformat:palantir-java-format:2.73.0") + palantir("com.palantir.javaformat:palantir-java-format:2.89.0") } fun registerPalantir( diff --git a/buildSrc/src/main/kotlin/finch.kotlin.gradle.kts b/buildSrc/src/main/kotlin/finch.kotlin.gradle.kts index 460dbc151..0b43c8cf3 100644 --- a/buildSrc/src/main/kotlin/finch.kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/finch.kotlin.gradle.kts @@ -40,7 +40,7 @@ tasks.withType().configureEach { val ktfmt by configurations.creating dependencies { - ktfmt("com.facebook:ktfmt:0.56") + ktfmt("com.facebook:ktfmt:0.61") } fun registerKtfmt( diff --git a/finch-java-client-okhttp/build.gradle.kts b/finch-java-client-okhttp/build.gradle.kts index 4adac97f0..9d168cf29 100644 --- a/finch-java-client-okhttp/build.gradle.kts +++ b/finch-java-client-okhttp/build.gradle.kts @@ -7,9 +7,8 @@ dependencies { api(project(":finch-java-core")) implementation("com.squareup.okhttp3:okhttp:4.12.0") - implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") testImplementation(kotlin("test")) - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") } diff --git a/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt b/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt index bc1394da7..d1dd65810 100644 --- a/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt +++ b/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClient.kt @@ -6,11 +6,13 @@ import com.fasterxml.jackson.databind.json.JsonMapper import com.tryfinch.api.client.FinchClient import com.tryfinch.api.client.FinchClientImpl import com.tryfinch.api.core.ClientOptions +import com.tryfinch.api.core.LogLevel import com.tryfinch.api.core.Sleeper import com.tryfinch.api.core.Timeout import com.tryfinch.api.core.http.AsyncStreamResponse import com.tryfinch.api.core.http.Headers import com.tryfinch.api.core.http.HttpClient +import com.tryfinch.api.core.http.ProxyAuthenticator import com.tryfinch.api.core.http.QueryParams import com.tryfinch.api.core.jsonMapper import java.net.Proxy @@ -49,6 +51,9 @@ class FinchOkHttpClient private constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null + private var proxyAuthenticator: ProxyAuthenticator? = null + private var maxIdleConnections: Int? = null + private var keepAliveDuration: Duration? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null @@ -77,6 +82,60 @@ class FinchOkHttpClient private constructor() { /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ fun proxy(proxy: Optional) = proxy(proxy.getOrNull()) + /** + * Provides credentials when an HTTP proxy responds with `407 Proxy Authentication + * Required`. + */ + fun proxyAuthenticator(proxyAuthenticator: ProxyAuthenticator?) = apply { + this.proxyAuthenticator = proxyAuthenticator + } + + /** + * Alias for calling [Builder.proxyAuthenticator] with `proxyAuthenticator.orElse(null)`. + */ + fun proxyAuthenticator(proxyAuthenticator: Optional) = + proxyAuthenticator(proxyAuthenticator.getOrNull()) + + /** + * The maximum number of idle connections kept by the underlying OkHttp connection pool. + * + * If this is set, then [keepAliveDuration] must also be set. + * + * If unset, then OkHttp's default is used. + */ + fun maxIdleConnections(maxIdleConnections: Int?) = apply { + this.maxIdleConnections = maxIdleConnections + } + + /** + * Alias for [Builder.maxIdleConnections]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun maxIdleConnections(maxIdleConnections: Int) = + maxIdleConnections(maxIdleConnections as Int?) + + /** + * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`. + */ + fun maxIdleConnections(maxIdleConnections: Optional) = + maxIdleConnections(maxIdleConnections.getOrNull()) + + /** + * The keep-alive duration for idle connections in the underlying OkHttp connection pool. + * + * If this is set, then [maxIdleConnections] must also be set. + * + * If unset, then OkHttp's default is used. + */ + fun keepAliveDuration(keepAliveDuration: Duration?) = apply { + this.keepAliveDuration = keepAliveDuration + } + + /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */ + fun keepAliveDuration(keepAliveDuration: Optional) = + keepAliveDuration(keepAliveDuration.getOrNull()) + /** * The socket factory used to secure HTTPS connections. * @@ -188,6 +247,9 @@ class FinchOkHttpClient private constructor() { /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -229,6 +291,15 @@ class FinchOkHttpClient private constructor() { */ fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + fun logLevel(logLevel: LogLevel) = apply { clientOptions.logLevel(logLevel) } + fun accessToken(accessToken: String?) = apply { clientOptions.accessToken(accessToken) } /** Alias for calling [Builder.accessToken] with `accessToken.orElse(null)`. */ @@ -351,6 +422,9 @@ class FinchOkHttpClient private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .proxyAuthenticator(proxyAuthenticator) + .maxIdleConnections(maxIdleConnections) + .keepAliveDuration(keepAliveDuration) .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) diff --git a/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt b/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt index 0e52b37ef..20378776f 100644 --- a/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt +++ b/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/FinchOkHttpClientAsync.kt @@ -6,11 +6,13 @@ import com.fasterxml.jackson.databind.json.JsonMapper import com.tryfinch.api.client.FinchClientAsync import com.tryfinch.api.client.FinchClientAsyncImpl import com.tryfinch.api.core.ClientOptions +import com.tryfinch.api.core.LogLevel import com.tryfinch.api.core.Sleeper import com.tryfinch.api.core.Timeout import com.tryfinch.api.core.http.AsyncStreamResponse import com.tryfinch.api.core.http.Headers import com.tryfinch.api.core.http.HttpClient +import com.tryfinch.api.core.http.ProxyAuthenticator import com.tryfinch.api.core.http.QueryParams import com.tryfinch.api.core.jsonMapper import java.net.Proxy @@ -49,6 +51,9 @@ class FinchOkHttpClientAsync private constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null + private var proxyAuthenticator: ProxyAuthenticator? = null + private var maxIdleConnections: Int? = null + private var keepAliveDuration: Duration? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null @@ -77,6 +82,60 @@ class FinchOkHttpClientAsync private constructor() { /** Alias for calling [Builder.proxy] with `proxy.orElse(null)`. */ fun proxy(proxy: Optional) = proxy(proxy.getOrNull()) + /** + * Provides credentials when an HTTP proxy responds with `407 Proxy Authentication + * Required`. + */ + fun proxyAuthenticator(proxyAuthenticator: ProxyAuthenticator?) = apply { + this.proxyAuthenticator = proxyAuthenticator + } + + /** + * Alias for calling [Builder.proxyAuthenticator] with `proxyAuthenticator.orElse(null)`. + */ + fun proxyAuthenticator(proxyAuthenticator: Optional) = + proxyAuthenticator(proxyAuthenticator.getOrNull()) + + /** + * The maximum number of idle connections kept by the underlying OkHttp connection pool. + * + * If this is set, then [keepAliveDuration] must also be set. + * + * If unset, then OkHttp's default is used. + */ + fun maxIdleConnections(maxIdleConnections: Int?) = apply { + this.maxIdleConnections = maxIdleConnections + } + + /** + * Alias for [Builder.maxIdleConnections]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun maxIdleConnections(maxIdleConnections: Int) = + maxIdleConnections(maxIdleConnections as Int?) + + /** + * Alias for calling [Builder.maxIdleConnections] with `maxIdleConnections.orElse(null)`. + */ + fun maxIdleConnections(maxIdleConnections: Optional) = + maxIdleConnections(maxIdleConnections.getOrNull()) + + /** + * The keep-alive duration for idle connections in the underlying OkHttp connection pool. + * + * If this is set, then [maxIdleConnections] must also be set. + * + * If unset, then OkHttp's default is used. + */ + fun keepAliveDuration(keepAliveDuration: Duration?) = apply { + this.keepAliveDuration = keepAliveDuration + } + + /** Alias for calling [Builder.keepAliveDuration] with `keepAliveDuration.orElse(null)`. */ + fun keepAliveDuration(keepAliveDuration: Optional) = + keepAliveDuration(keepAliveDuration.getOrNull()) + /** * The socket factory used to secure HTTPS connections. * @@ -188,6 +247,9 @@ class FinchOkHttpClientAsync private constructor() { /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -229,6 +291,15 @@ class FinchOkHttpClientAsync private constructor() { */ fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + fun logLevel(logLevel: LogLevel) = apply { clientOptions.logLevel(logLevel) } + fun accessToken(accessToken: String?) = apply { clientOptions.accessToken(accessToken) } /** Alias for calling [Builder.accessToken] with `accessToken.orElse(null)`. */ @@ -351,6 +422,9 @@ class FinchOkHttpClientAsync private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .proxyAuthenticator(proxyAuthenticator) + .maxIdleConnections(maxIdleConnections) + .keepAliveDuration(keepAliveDuration) .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) diff --git a/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/OkHttpClient.kt b/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/OkHttpClient.kt index a40937a40..fc3ffd5be 100644 --- a/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/OkHttpClient.kt +++ b/finch-java-client-okhttp/src/main/kotlin/com/tryfinch/api/client/okhttp/OkHttpClient.kt @@ -8,20 +8,26 @@ import com.tryfinch.api.core.http.HttpMethod import com.tryfinch.api.core.http.HttpRequest import com.tryfinch.api.core.http.HttpRequestBody import com.tryfinch.api.core.http.HttpResponse +import com.tryfinch.api.core.http.ProxyAuthenticator import com.tryfinch.api.errors.FinchIoException import java.io.IOException import java.io.InputStream +import java.io.OutputStream import java.net.Proxy import java.time.Duration import java.util.concurrent.CancellationException import java.util.concurrent.CompletableFuture import java.util.concurrent.ExecutorService +import java.util.concurrent.TimeUnit import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager +import kotlin.jvm.optionals.getOrNull import okhttp3.Call import okhttp3.Callback +import okhttp3.ConnectionPool import okhttp3.Dispatcher +import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType @@ -29,17 +35,18 @@ import okhttp3.Request import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.Response -import okhttp3.logging.HttpLoggingInterceptor import okio.BufferedSink +import okio.buffer +import okio.sink class OkHttpClient -private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient { +internal constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClient) : HttpClient { override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { val call = newCall(request, requestOptions) return try { - call.execute().toResponse() + call.execute().toHttpResponse() } catch (e: IOException) { throw FinchIoException("Request failed", e) } finally { @@ -57,7 +64,7 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien call.enqueue( object : Callback { override fun onResponse(call: Call, response: Response) { - future.complete(response.toResponse()) + future.complete(response.toHttpResponse()) } override fun onFailure(call: Call, e: IOException) { @@ -85,18 +92,6 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call { val clientBuilder = okHttpClient.newBuilder() - val logLevel = - when (System.getenv("FINCH_LOG")?.lowercase()) { - "info" -> HttpLoggingInterceptor.Level.BASIC - "debug" -> HttpLoggingInterceptor.Level.BODY - else -> null - } - if (logLevel != null) { - clientBuilder.addNetworkInterceptor( - HttpLoggingInterceptor().setLevel(logLevel).apply { redactHeader("Authorization") } - ) - } - requestOptions.timeout?.let { clientBuilder .connectTimeout(it.connect()) @@ -109,89 +104,6 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien return client.newCall(request.toRequest(client)) } - private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient): Request { - var body: RequestBody? = body?.toRequestBody() - if (body == null && requiresBody(method)) { - body = "".toRequestBody() - } - - val builder = Request.Builder().url(toUrl()).method(method.name, body) - headers.names().forEach { name -> - headers.values(name).forEach { builder.addHeader(name, it) } - } - - if ( - !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0 - ) { - builder.addHeader( - "X-Stainless-Read-Timeout", - Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(), - ) - } - if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) { - builder.addHeader( - "X-Stainless-Timeout", - Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(), - ) - } - - return builder.build() - } - - /** `OkHttpClient` always requires a request body for some methods. */ - private fun requiresBody(method: HttpMethod): Boolean = - when (method) { - HttpMethod.POST, - HttpMethod.PUT, - HttpMethod.PATCH -> true - else -> false - } - - private fun HttpRequest.toUrl(): String { - val builder = baseUrl.toHttpUrl().newBuilder() - pathSegments.forEach(builder::addPathSegment) - queryParams.keys().forEach { key -> - queryParams.values(key).forEach { builder.addQueryParameter(key, it) } - } - - return builder.toString() - } - - private fun HttpRequestBody.toRequestBody(): RequestBody { - val mediaType = contentType()?.toMediaType() - val length = contentLength() - - return object : RequestBody() { - override fun contentType(): MediaType? = mediaType - - override fun contentLength(): Long = length - - override fun isOneShot(): Boolean = !repeatable() - - override fun writeTo(sink: BufferedSink) = writeTo(sink.outputStream()) - } - } - - private fun Response.toResponse(): HttpResponse { - val headers = headers.toHeaders() - - return object : HttpResponse { - override fun statusCode(): Int = code - - override fun headers(): Headers = headers - - override fun body(): InputStream = body!!.byteStream() - - override fun close() = body!!.close() - } - } - - private fun okhttp3.Headers.toHeaders(): Headers { - val headersBuilder = Headers.builder() - forEach { (name, value) -> headersBuilder.put(name, value) } - return headersBuilder.build() - } - companion object { @JvmStatic fun builder() = Builder() } @@ -200,6 +112,9 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien private var timeout: Timeout = Timeout.default() private var proxy: Proxy? = null + private var proxyAuthenticator: ProxyAuthenticator? = null + private var maxIdleConnections: Int? = null + private var keepAliveDuration: Duration? = null private var dispatcherExecutorService: ExecutorService? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null @@ -211,6 +126,32 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + fun proxyAuthenticator(proxyAuthenticator: ProxyAuthenticator?) = apply { + this.proxyAuthenticator = proxyAuthenticator + } + + /** + * Sets the maximum number of idle connections kept by the underlying [ConnectionPool]. + * + * If this is set, then [keepAliveDuration] must also be set. + * + * If unset, then OkHttp's default is used. + */ + fun maxIdleConnections(maxIdleConnections: Int?) = apply { + this.maxIdleConnections = maxIdleConnections + } + + /** + * Sets the keep-alive duration for idle connections in the underlying [ConnectionPool]. + * + * If this is set, then [maxIdleConnections] must also be set. + * + * If unset, then OkHttp's default is used. + */ + fun keepAliveDuration(keepAliveDuration: Duration?) = apply { + this.keepAliveDuration = keepAliveDuration + } + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { this.dispatcherExecutorService = dispatcherExecutorService } @@ -238,8 +179,37 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien .callTimeout(timeout.request()) .proxy(proxy) .apply { + proxyAuthenticator?.let { auth -> + proxyAuthenticator { route, response -> + auth + .authenticate( + route?.proxy ?: Proxy.NO_PROXY, + response.request.toHttpRequest(), + response.toHttpResponse(), + ) + .getOrNull() + ?.toRequest(client = null) + } + } + dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) } + val maxIdleConnections = maxIdleConnections + val keepAliveDuration = keepAliveDuration + if (maxIdleConnections != null && keepAliveDuration != null) { + connectionPool( + ConnectionPool( + maxIdleConnections, + keepAliveDuration.toNanos(), + TimeUnit.NANOSECONDS, + ) + ) + } else { + check((maxIdleConnections != null) == (keepAliveDuration != null)) { + "Both or none of `maxIdleConnections` and `keepAliveDuration` must be set, but only one was set" + } + } + val sslSocketFactory = sslSocketFactory val trustManager = trustManager if (sslSocketFactory != null && trustManager != null) { @@ -261,3 +231,126 @@ private constructor(@JvmSynthetic internal val okHttpClient: okhttp3.OkHttpClien ) } } + +private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient?): Request { + var body: RequestBody? = body?.toRequestBody() + if (body == null && requiresBody(method)) { + body = "".toRequestBody() + } + + val builder = Request.Builder().url(toUrl()).method(method.name, body) + headers.names().forEach { name -> headers.values(name).forEach { builder.addHeader(name, it) } } + + if (client != null) { + if ( + !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0 + ) { + builder.addHeader( + "X-Stainless-Read-Timeout", + Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString(), + ) + } + if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) { + builder.addHeader( + "X-Stainless-Timeout", + Duration.ofMillis(client.callTimeoutMillis.toLong()).seconds.toString(), + ) + } + } + + return builder.build() +} + +/** `OkHttpClient` always requires a request body for some methods. */ +private fun requiresBody(method: HttpMethod): Boolean = + when (method) { + HttpMethod.POST, + HttpMethod.PUT, + HttpMethod.PATCH -> true + else -> false + } + +private fun HttpRequest.toUrl(): String { + val builder = baseUrl.toHttpUrl().newBuilder() + pathSegments.forEach(builder::addPathSegment) + queryParams.keys().forEach { key -> + queryParams.values(key).forEach { builder.addQueryParameter(key, it) } + } + + return builder.toString() +} + +private fun HttpRequestBody.toRequestBody(): RequestBody { + val mediaType = contentType()?.toMediaType() + val length = contentLength() + + return object : RequestBody() { + override fun contentType(): MediaType? = mediaType + + override fun contentLength(): Long = length + + override fun isOneShot(): Boolean = !repeatable() + + override fun writeTo(sink: BufferedSink) = writeTo(sink.outputStream()) + } +} + +private fun Request.toHttpRequest(): HttpRequest { + val builder = HttpRequest.builder().method(HttpMethod.valueOf(method)).baseUrl(url.toBaseUrl()) + url.pathSegments.forEach(builder::addPathSegment) + url.queryParameterNames.forEach { name -> + url.queryParameterValues(name).filterNotNull().forEach { builder.putQueryParam(name, it) } + } + headers.forEach { (name, value) -> builder.putHeader(name, value) } + body?.let { builder.body(it.toHttpRequestBody()) } + return builder.build() +} + +private fun HttpUrl.toBaseUrl(): String = buildString { + append(scheme).append("://").append(host) + if (port != HttpUrl.defaultPort(scheme)) { + append(":").append(port) + } +} + +private fun RequestBody.toHttpRequestBody(): HttpRequestBody { + val mediaType = contentType()?.toString() + val length = contentLength() + val isOneShot = isOneShot() + val source = this + return object : HttpRequestBody { + override fun contentType(): String? = mediaType + + override fun contentLength(): Long = length + + override fun repeatable(): Boolean = !isOneShot + + override fun writeTo(outputStream: OutputStream) { + val sink = outputStream.sink().buffer() + source.writeTo(sink) + sink.flush() + } + + override fun close() {} + } +} + +private fun Response.toHttpResponse(): HttpResponse { + val headers = headers.toHeaders() + + return object : HttpResponse { + override fun statusCode(): Int = code + + override fun headers(): Headers = headers + + override fun body(): InputStream = body!!.byteStream() + + override fun close() = body!!.close() + } +} + +private fun okhttp3.Headers.toHeaders(): Headers { + val headersBuilder = Headers.builder() + forEach { (name, value) -> headersBuilder.put(name, value) } + return headersBuilder.build() +} diff --git a/finch-java-core/build.gradle.kts b/finch-java-core/build.gradle.kts index a8087c75c..d5dc8c35f 100644 --- a/finch-java-core/build.gradle.kts +++ b/finch-java-core/build.gradle.kts @@ -27,13 +27,11 @@ dependencies { implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.2") implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.2") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.2") - implementation("org.apache.httpcomponents.core5:httpcore5:5.2.4") - implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1") testImplementation(kotlin("test")) testImplementation(project(":finch-java-client-okhttp")) testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.3") testImplementation("org.junit-pioneer:junit-pioneer:1.9.1") diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ClientOptions.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ClientOptions.kt index fbecf1953..90539b872 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ClientOptions.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ClientOptions.kt @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.json.JsonMapper import com.tryfinch.api.core.http.AsyncStreamResponse import com.tryfinch.api.core.http.Headers import com.tryfinch.api.core.http.HttpClient +import com.tryfinch.api.core.http.LoggingHttpClient import com.tryfinch.api.core.http.PhantomReachableClosingHttpClient import com.tryfinch.api.core.http.QueryParams import com.tryfinch.api.core.http.RetryingHttpClient @@ -81,6 +82,9 @@ private constructor( /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for existing + * fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -108,6 +112,14 @@ private constructor( * Defaults to 2. */ @get:JvmName("maxRetries") val maxRetries: Int, + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + @get:JvmName("logLevel") val logLevel: LogLevel, private val accessToken: String?, private val clientId: String?, private val clientSecret: String?, @@ -174,6 +186,7 @@ private constructor( private var responseValidation: Boolean = false private var timeout: Timeout = Timeout.default() private var maxRetries: Int = 2 + private var logLevel: LogLevel = LogLevel.fromEnv() private var accessToken: String? = null private var clientId: String? = null private var clientSecret: String? = null @@ -193,6 +206,7 @@ private constructor( responseValidation = clientOptions.responseValidation timeout = clientOptions.timeout maxRetries = clientOptions.maxRetries + logLevel = clientOptions.logLevel accessToken = clientOptions.accessToken clientId = clientOptions.clientId clientSecret = clientOptions.clientSecret @@ -276,6 +290,9 @@ private constructor( /** * Whether to call `validate` on every response before returning it. * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * * Defaults to false, which means the shape of the response will not be validated upfront. * Instead, validation will only occur for the parts of the response that are accessed. */ @@ -317,6 +334,15 @@ private constructor( */ fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } + /** + * The level at which to log request and response information. + * + * [fromEnv] will set the level from environment variables. See [LogLevel.fromEnv]. + * + * Defaults to [LogLevel.fromEnv]. + */ + fun logLevel(logLevel: LogLevel) = apply { this.logLevel = logLevel } + fun accessToken(accessToken: String?) = apply { this.accessToken = accessToken } /** Alias for calling [Builder.accessToken] with `accessToken.orElse(null)`. */ @@ -435,6 +461,7 @@ private constructor( * System properties take precedence over environment variables. */ fun fromEnv() = apply { + logLevel(LogLevel.fromEnv()) (System.getProperty("finch.baseUrl") ?: System.getenv("FINCH_BASE_URL"))?.let { baseUrl(it) } @@ -445,6 +472,14 @@ private constructor( ?.let { clientSecret(it) } (System.getProperty("finch.webhookSecret") ?: System.getenv("FINCH_WEBHOOK_SECRET")) ?.let { webhookSecret(it) } + System.getenv("FINCH_CUSTOM_HEADERS")?.let { customHeadersEnv -> + for (line in customHeadersEnv.split("\n")) { + val colon = line.indexOf(':') + if (colon >= 0) { + putHeader(line.substring(0, colon).trim(), line.substring(colon + 1).trim()) + } + } + } } /** @@ -513,7 +548,13 @@ private constructor( return ClientOptions( httpClient, RetryingHttpClient.builder() - .httpClient(httpClient) + .httpClient( + LoggingHttpClient.builder() + .httpClient(httpClient) + .clock(clock) + .level(logLevel) + .build() + ) .sleeper(sleeper) .clock(clock) .maxRetries(maxRetries) @@ -529,6 +570,7 @@ private constructor( responseValidation, timeout, maxRetries, + logLevel, accessToken, clientId, clientSecret, @@ -552,4 +594,29 @@ private constructor( (streamHandlerExecutor as? ExecutorService)?.shutdown() sleeper.close() } + + @JvmSynthetic + internal fun securityHeaders(security: SecurityOptions): Headers { + val headers = Headers.builder() + if (security.bearerAuth) { + accessToken?.let { + if (!it.isEmpty()) { + headers.replace("Authorization", "Bearer $it") + } + } + } + if (security.basicAuth) { + clientId?.let { username -> + clientSecret?.let { password -> + if (!username.isEmpty() && !password.isEmpty()) { + headers.replace( + "Authorization", + "Basic ${Base64.getEncoder().encodeToString("$username:$password".toByteArray())}", + ) + } + } + } + } + return headers.build() + } } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/LogLevel.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/LogLevel.kt new file mode 100644 index 000000000..2891f6668 --- /dev/null +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/LogLevel.kt @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.tryfinch.api.core + +/** The level at which to log request and response information. */ +enum class LogLevel { + /** No logging. */ + OFF, + /** Minimal request and response summary logs. No headers or bodies are logged. */ + INFO, + /** [INFO] logs plus details about request failures. */ + ERROR, + /** + * Full request and response logs. Sensitive headers are redacted, but sensitive data in request + * and response bodies may still be visible. + */ + DEBUG; + + /** Returns whether this level is at or higher than the given [level]. */ + fun shouldLog(level: LogLevel): Boolean = ordinal >= level.ordinal + + companion object { + + /** Returns a [LogLevel] based on the `FINCH_LOG` environment variable. */ + fun fromEnv() = + when (System.getenv("FINCH_LOG")?.lowercase()) { + "info" -> INFO + "error" -> ERROR + "debug" -> DEBUG + else -> OFF + } + } +} diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ObjectMappers.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ObjectMappers.kt index 5ad93de49..7a3ddcb33 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ObjectMappers.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/ObjectMappers.kt @@ -29,7 +29,9 @@ import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.temporal.ChronoField -fun jsonMapper(): JsonMapper = +fun jsonMapper(): JsonMapper = JSON_MAPPER + +private val JSON_MAPPER: JsonMapper = JsonMapper.builder() .addModule(kotlinModule()) .addModule(Jdk8Module()) diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/PrepareRequest.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/PrepareRequest.kt index 6e1aaafb2..d5d2a9c33 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/PrepareRequest.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/PrepareRequest.kt @@ -6,10 +6,15 @@ import com.tryfinch.api.core.http.HttpRequest import java.util.concurrent.CompletableFuture @JvmSynthetic -internal fun HttpRequest.prepare(clientOptions: ClientOptions, params: Params): HttpRequest = +internal fun HttpRequest.prepare( + clientOptions: ClientOptions, + params: Params, + security: SecurityOptions = SecurityOptions.all(), +): HttpRequest = toBuilder() .putAllQueryParams(clientOptions.queryParams) .replaceAllQueryParams(params._queryParams()) + .putAllHeaders(clientOptions.securityHeaders(security)) .putAllHeaders(clientOptions.headers) .replaceAllHeaders(params._headers()) .build() @@ -18,7 +23,8 @@ internal fun HttpRequest.prepare(clientOptions: ClientOptions, params: Params): internal fun HttpRequest.prepareAsync( clientOptions: ClientOptions, params: Params, + security: SecurityOptions = SecurityOptions.all(), ): CompletableFuture = // This async version exists to make it easier to add async specific preparation logic in the // future. - CompletableFuture.completedFuture(prepare(clientOptions, params)) + CompletableFuture.completedFuture(prepare(clientOptions, params, security)) diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Properties.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Properties.kt index 29bb4994f..795814992 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Properties.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Properties.kt @@ -34,9 +34,9 @@ fun getOsName(): String { } } -fun getOsVersion(): String = System.getProperty("os.version", "unknown") +fun getOsVersion(): String = System.getProperty("os.version", "unknown") ?: "unknown" fun getPackageVersion(): String = - FinchClient::class.java.`package`.implementationVersion ?: "unknown" + FinchClient::class.java.`package`?.implementationVersion ?: "unknown" -fun getJavaVersion(): String = System.getProperty("java.version", "unknown") +fun getJavaVersion(): String = System.getProperty("java.version", "unknown") ?: "unknown" diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/RequestOptions.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/RequestOptions.kt index 89fdd644c..c31a5b33e 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/RequestOptions.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/RequestOptions.kt @@ -33,6 +33,15 @@ class RequestOptions private constructor(val responseValidation: Boolean?, val t private var responseValidation: Boolean? = null private var timeout: Timeout? = null + /** + * Whether to call `validate` on the response before returning it. + * + * Setting this to `true` is _not_ forwards compatible with new types from the API for + * existing fields. + * + * Defaults to false, which means the shape of the response will not be validated upfront. + * Instead, validation will only occur for the parts of the response that are accessed. + */ fun responseValidation(responseValidation: Boolean) = apply { this.responseValidation = responseValidation } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/SecurityOptions.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/SecurityOptions.kt new file mode 100644 index 000000000..d4b5d0d5b --- /dev/null +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/SecurityOptions.kt @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.tryfinch.api.core + +import java.util.Objects + +/** A class for configuring which security schemes are enabled for a request. */ +class SecurityOptions +private constructor( + /** Whether the bearerAuth security scheme is enabled. */ + @get:JvmName("bearerAuth") val bearerAuth: Boolean, + /** Whether the basicAuth security scheme is enabled. */ + @get:JvmName("basicAuth") val basicAuth: Boolean, +) { + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [SecurityOptions]. */ + @JvmStatic fun builder() = Builder() + + /** Returns a [Security] instance with all security schemes enabled. */ + @JvmStatic fun all(): SecurityOptions = builder().bearerAuth(true).basicAuth(true).build() + + /** Returns a [Security] instance with no security schemes enabled. */ + @JvmStatic fun none(): SecurityOptions = builder().build() + } + + /** A builder for [SecurityOptions]. */ + class Builder internal constructor() { + + private var bearerAuth: Boolean = false + private var basicAuth: Boolean = false + + @JvmSynthetic + internal fun from(securityOptions: SecurityOptions) = apply { + bearerAuth = securityOptions.bearerAuth + basicAuth = securityOptions.basicAuth + } + + /** Whether the bearerAuth security scheme is enabled. */ + fun bearerAuth(bearerAuth: Boolean) = apply { this.bearerAuth = bearerAuth } + + /** Whether the basicAuth security scheme is enabled. */ + fun basicAuth(basicAuth: Boolean) = apply { this.basicAuth = basicAuth } + + /** + * Returns an immutable instance of [SecurityOptions]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): SecurityOptions = SecurityOptions(bearerAuth, basicAuth) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is SecurityOptions && + bearerAuth == other.bearerAuth && + basicAuth == other.basicAuth + } + + override fun hashCode(): Int = Objects.hash(bearerAuth, basicAuth) + + override fun toString() = "SecurityOptions{bearerAuth=$bearerAuth, basicAuth=$basicAuth}" +} diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Utils.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Utils.kt index 7580ba7ba..a2604d611 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Utils.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/Utils.kt @@ -6,6 +6,7 @@ import com.tryfinch.api.core.http.Headers import com.tryfinch.api.errors.FinchInvalidDataException import java.util.Collections import java.util.SortedMap +import java.util.SortedSet import java.util.concurrent.CompletableFuture import java.util.concurrent.locks.Lock @@ -17,6 +18,11 @@ internal fun T?.getOrThrow(name: String): T = internal fun List.toImmutable(): List = if (isEmpty()) Collections.emptyList() else Collections.unmodifiableList(toList()) +@JvmSynthetic +internal fun > SortedSet.toImmutable(): SortedSet = + if (isEmpty()) Collections.emptySortedSet() + else Collections.unmodifiableSortedSet(toSortedSet(comparator() ?: Comparator.naturalOrder())) + @JvmSynthetic internal fun Map.toImmutable(): Map = if (isEmpty()) immutableEmptyMap() else Collections.unmodifiableMap(toMap()) diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/HttpRequestBodies.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/HttpRequestBodies.kt index 9aee7f83b..83ab12669 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/HttpRequestBodies.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/HttpRequestBodies.kt @@ -8,13 +8,13 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.databind.node.JsonNodeType import com.tryfinch.api.core.MultipartField +import com.tryfinch.api.core.toImmutable import com.tryfinch.api.errors.FinchInvalidDataException +import java.io.ByteArrayInputStream import java.io.InputStream import java.io.OutputStream +import java.util.UUID import kotlin.jvm.optionals.getOrNull -import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder -import org.apache.hc.core5.http.ContentType -import org.apache.hc.core5.http.HttpEntity @JvmSynthetic internal inline fun json(jsonMapper: JsonMapper, value: T): HttpRequestBody = @@ -37,70 +37,207 @@ internal fun multipartFormData( jsonMapper: JsonMapper, fields: Map>, ): HttpRequestBody = - object : HttpRequestBody { - private val entity: HttpEntity by lazy { - MultipartEntityBuilder.create() - .apply { - fields.forEach { (name, field) -> - val knownValue = field.value.asKnown().getOrNull() - val parts = - if (knownValue is InputStream) { - // Read directly from the `InputStream` instead of reading it all - // into memory due to the `jsonMapper` serialization below. - sequenceOf(name to knownValue) - } else { - val node = jsonMapper.valueToTree(field.value) - serializePart(name, node) + MultipartBody.Builder() + .apply { + fields.forEach { (name, field) -> + val knownValue = field.value.asKnown().getOrNull() + val parts = + if (knownValue is InputStream) { + // Read directly from the `InputStream` instead of reading it all + // into memory due to the `jsonMapper` serialization below. + sequenceOf(name to knownValue) + } else { + val node = jsonMapper.valueToTree(field.value) + serializePart(name, node) + } + + parts.forEach { (name, bytes) -> + val partBody = + if (bytes is ByteArrayInputStream) { + val byteArray = bytes.readBytes() + + object : HttpRequestBody { + + override fun writeTo(outputStream: OutputStream) { + outputStream.write(byteArray) + } + + override fun contentType(): String = field.contentType + + override fun contentLength(): Long = byteArray.size.toLong() + + override fun repeatable(): Boolean = true + + override fun close() {} } + } else { + object : HttpRequestBody { + + override fun writeTo(outputStream: OutputStream) { + bytes.copyTo(outputStream) + } + + override fun contentType(): String = field.contentType - parts.forEach { (name, bytes) -> - addBinaryBody( - name, - bytes, - ContentType.parseLenient(field.contentType), - field.filename().getOrNull(), - ) + override fun contentLength(): Long = -1L + + override fun repeatable(): Boolean = false + + override fun close() = bytes.close() + } } - } + + addPart( + MultipartBody.Part.create( + name, + field.filename().getOrNull(), + field.contentType, + partBody, + ) + ) } - .build() + } } + .build() + +private fun serializePart(name: String, node: JsonNode): Sequence> = + when (node.nodeType) { + JsonNodeType.MISSING, + JsonNodeType.NULL -> emptySequence() + JsonNodeType.BINARY -> sequenceOf(name to node.binaryValue().inputStream()) + JsonNodeType.STRING -> sequenceOf(name to node.textValue().byteInputStream()) + JsonNodeType.BOOLEAN -> sequenceOf(name to node.booleanValue().toString().byteInputStream()) + JsonNodeType.NUMBER -> sequenceOf(name to node.numberValue().toString().byteInputStream()) + JsonNodeType.ARRAY -> + node.elements().asSequence().flatMap { element -> serializePart("$name[]", element) } + JsonNodeType.OBJECT -> + node.fields().asSequence().flatMap { (key, value) -> + serializePart("$name[$key]", value) + } + JsonNodeType.POJO, + null -> throw FinchInvalidDataException("Unexpected JsonNode type: ${node.nodeType}") + } - private fun serializePart( - name: String, - node: JsonNode, - ): Sequence> = - when (node.nodeType) { - JsonNodeType.MISSING, - JsonNodeType.NULL -> emptySequence() - JsonNodeType.BINARY -> sequenceOf(name to node.binaryValue().inputStream()) - JsonNodeType.STRING -> sequenceOf(name to node.textValue().inputStream()) - JsonNodeType.BOOLEAN -> - sequenceOf(name to node.booleanValue().toString().inputStream()) - JsonNodeType.NUMBER -> - sequenceOf(name to node.numberValue().toString().inputStream()) - JsonNodeType.ARRAY -> - node.elements().asSequence().flatMap { element -> - serializePart("$name[]", element) - } - JsonNodeType.OBJECT -> - node.fields().asSequence().flatMap { (key, value) -> - serializePart("$name[$key]", value) - } - JsonNodeType.POJO, - null -> - throw FinchInvalidDataException("Unexpected JsonNode type: ${node.nodeType}") +private class MultipartBody +private constructor(private val boundary: String, private val parts: List) : HttpRequestBody { + private val boundaryBytes: ByteArray = boundary.toByteArray() + private val contentType = "multipart/form-data; boundary=$boundary" + + // This must remain in sync with `contentLength`. + override fun writeTo(outputStream: OutputStream) { + parts.forEach { part -> + outputStream.write(DASHDASH) + outputStream.write(boundaryBytes) + outputStream.write(CRLF) + + outputStream.write(CONTENT_DISPOSITION) + outputStream.write(part.contentDisposition.toByteArray()) + outputStream.write(CRLF) + + outputStream.write(CONTENT_TYPE) + outputStream.write(part.contentType.toByteArray()) + outputStream.write(CRLF) + + outputStream.write(CRLF) + part.body.writeTo(outputStream) + outputStream.write(CRLF) + } + + outputStream.write(DASHDASH) + outputStream.write(boundaryBytes) + outputStream.write(DASHDASH) + outputStream.write(CRLF) + } + + override fun contentType(): String = contentType + + // This must remain in sync with `writeTo`. + override fun contentLength(): Long { + var byteCount = 0L + + parts.forEach { part -> + val contentLength = part.body.contentLength() + if (contentLength == -1L) { + return -1L } - private fun String.inputStream(): InputStream = toByteArray().inputStream() + byteCount += + DASHDASH.size + + boundaryBytes.size + + CRLF.size + + CONTENT_DISPOSITION.size + + part.contentDisposition.toByteArray().size + + CRLF.size + + CONTENT_TYPE.size + + part.contentType.toByteArray().size + + CRLF.size + + CRLF.size + + contentLength + + CRLF.size + } - override fun writeTo(outputStream: OutputStream) = entity.writeTo(outputStream) + byteCount += DASHDASH.size + boundaryBytes.size + DASHDASH.size + CRLF.size + return byteCount + } - override fun contentType(): String = entity.contentType + override fun repeatable(): Boolean = parts.all { it.body.repeatable() } - override fun contentLength(): Long = entity.contentLength + override fun close() { + parts.forEach { it.body.close() } + } - override fun repeatable(): Boolean = entity.isRepeatable + class Builder { + private val boundary = UUID.randomUUID().toString() + private val parts: MutableList = mutableListOf() - override fun close() = entity.close() + fun addPart(part: Part) = apply { parts.add(part) } + + fun build() = MultipartBody(boundary, parts.toImmutable()) + } + + class Part + private constructor( + val contentDisposition: String, + val contentType: String, + val body: HttpRequestBody, + ) { + companion object { + fun create( + name: String, + filename: String?, + contentType: String, + body: HttpRequestBody, + ): Part { + val disposition = buildString { + append("form-data; name=") + appendQuotedString(name) + if (filename != null) { + append("; filename=") + appendQuotedString(filename) + } + } + return Part(disposition, contentType, body) + } + } + } + + companion object { + private val CRLF = byteArrayOf('\r'.code.toByte(), '\n'.code.toByte()) + private val DASHDASH = byteArrayOf('-'.code.toByte(), '-'.code.toByte()) + private val CONTENT_DISPOSITION = "Content-Disposition: ".toByteArray() + private val CONTENT_TYPE = "Content-Type: ".toByteArray() + + private fun StringBuilder.appendQuotedString(key: String) { + append('"') + for (ch in key) { + when (ch) { + '\n' -> append("%0A") + '\r' -> append("%0D") + '"' -> append("%22") + else -> append(ch) + } + } + append('"') + } } +} diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/LoggingHttpClient.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/LoggingHttpClient.kt new file mode 100644 index 000000000..a71ba5388 --- /dev/null +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/LoggingHttpClient.kt @@ -0,0 +1,628 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.tryfinch.api.core.http + +import com.tryfinch.api.core.LogLevel +import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.checkRequired +import com.tryfinch.api.core.toImmutable +import java.io.ByteArrayOutputStream +import java.io.InputStream +import java.io.OutputStream +import java.nio.ByteBuffer +import java.nio.charset.CharacterCodingException +import java.nio.charset.Charset +import java.nio.charset.CharsetDecoder +import java.nio.charset.CodingErrorAction +import java.nio.charset.StandardCharsets +import java.time.Clock +import java.time.Duration +import java.time.OffsetDateTime +import java.util.SortedSet +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CompletionException +import kotlin.time.toKotlinDuration + +/** A wrapper [HttpClient] around [httpClient] that logs request and response information. */ +class LoggingHttpClient +private constructor( + /** The underlying [HttpClient] for making requests. */ + @get:JvmName("httpClient") val httpClient: HttpClient, + /** + * Sensitive headers to redact from logs. + * + * Defaults to `Set.of("authorization", "api-key", "x-api-key", "cookie", "set-cookie")`. + */ + @get:JvmName("redactedHeaders") val redactedHeaders: SortedSet, + /** + * The clock to use for measuring request and response durations. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + @get:JvmName("clock") val clock: Clock, + /** + * The log level to use. + * + * Pass [LogLevel.fromEnv] to read from environment variables. + */ + @get:JvmName("level") val level: LogLevel, +) : HttpClient { + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { + val loggingRequest = logRequest(request) + + val before = OffsetDateTime.now(clock) + val response = + try { + httpClient.execute(loggingRequest, requestOptions) + } catch (e: Throwable) { + logFailure(e, Duration.between(before, OffsetDateTime.now(clock))) + throw e + } + + val took = Duration.between(before, OffsetDateTime.now(clock)) + return logResponse(response, took) + } + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture { + val loggingRequest = logRequest(request) + + val before = OffsetDateTime.now(clock) + val future = + try { + httpClient.executeAsync(loggingRequest, requestOptions) + } catch (e: Throwable) { + logFailure(e, Duration.between(before, OffsetDateTime.now(clock))) + throw e + } + return future.handle { response, error -> + val took = Duration.between(before, OffsetDateTime.now(clock)) + if (error != null) { + logFailure(unwrapCompletionException(error), took) + throw error + } + logResponse(response, took) + } + } + + private fun logRequest(request: HttpRequest): HttpRequest { + if (!level.shouldLog(LogLevel.INFO)) { + return request + } + + System.err.println( + buildString { + append("--> ${request.method} ${request.url()}") + request.body?.let { + val length = it.contentLength() + append(if (length >= 0) " ($length-byte body)" else " (unknown-length body)") + } + } + ) + + if (!level.shouldLog(LogLevel.DEBUG)) { + return request + } + + logHeaders(request.headers) + + if (request.body == null) { + System.err.println("--> END ${request.method}") + System.err.println() + return request + } + + return request + .toBuilder() + .body(LoggingHttpRequestBody(request.method, request.body)) + .build() + } + + private fun logResponse(response: HttpResponse, took: Duration): HttpResponse { + if (!level.shouldLog(LogLevel.INFO)) { + return response + } + + val contentLength = response.headers().values("Content-Length").firstOrNull()?.toIntOrNull() + System.err.println( + "<-- ${response.statusCode()} (${ + buildString { + append(took.format()) + contentLength?.let { append(", $contentLength-byte body") } + } + })" + ) + + if (!level.shouldLog(LogLevel.DEBUG)) { + return response + } + + logHeaders(response.headers()) + return LoggingHttpResponse(response) + } + + private fun logFailure(error: Throwable, took: Duration) { + if (!level.shouldLog(LogLevel.ERROR)) { + return + } + + System.err.println( + buildString { + append("<-- !! ${error.javaClass.simpleName}") + error.message?.let { append(": $it") } + append(" (${took.format()})") + } + ) + } + + private fun unwrapCompletionException(error: Throwable): Throwable = + if (error is CompletionException && error.cause != null) error.cause!! else error + + private fun logHeaders(headers: Headers) = + headers.names().forEach { name -> + headers.values(name).forEach { value -> + System.err.println("$name: ${if (redactedHeaders.contains(name)) "██" else value}") + } + } + + override fun close() = httpClient.close() + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [LoggingHttpClient]. + * + * The following fields are required: + * ```java + * .httpClient() + * .level() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [LoggingHttpClient]. */ + class Builder internal constructor() { + + private var httpClient: HttpClient? = null + private var redactedHeaders: Set = + setOf("authorization", "api-key", "x-api-key", "cookie", "set-cookie") + private var clock: Clock = Clock.systemUTC() + private var level: LogLevel? = null + + @JvmSynthetic + internal fun from(loggingHttpClient: LoggingHttpClient) = apply { + httpClient = loggingHttpClient.httpClient + redactedHeaders = loggingHttpClient.redactedHeaders + clock = loggingHttpClient.clock + level = loggingHttpClient.level + } + + /** The underlying [HttpClient] for making requests. */ + fun httpClient(httpClient: HttpClient) = apply { this.httpClient = httpClient } + + /** + * Sensitive headers to redact from logs. + * + * Defaults to `Set.of("authorization", "api-key", "x-api-key", "cookie", "set-cookie")`. + */ + fun redactedHeaders(redactedHeaders: Set) = apply { + this.redactedHeaders = redactedHeaders + } + + /** + * The clock to use for measuring request and response durations. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { this.clock = clock } + + /** + * The log level to use. + * + * Pass [LogLevel.fromEnv] to read from environment variables. + */ + fun level(level: LogLevel) = apply { this.level = level } + + /** + * Returns an immutable instance of [LoggingHttpClient]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .httpClient() + * .level() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): LoggingHttpClient = + LoggingHttpClient( + checkRequired("httpClient", httpClient), + redactedHeaders.toSortedSet(String.CASE_INSENSITIVE_ORDER).toImmutable(), + clock, + checkRequired("level", level), + ) + } +} + +/** + * An [HttpRequestBody] wrapper that delegates to [body] while also logging line by line as it's + * written. + * + * The logging occurs in a streaming manner with minimal buffering. + */ +private class LoggingHttpRequestBody( + private val method: HttpMethod, + private val body: HttpRequestBody, +) : HttpRequestBody { + + private val charset by lazy { parseCharset(body.contentType()) } + + override fun writeTo(outputStream: OutputStream) { + val loggingOutputStream = LoggingOutputStream(outputStream, charset) + body.writeTo(loggingOutputStream) + + loggingOutputStream.flush() + System.err.println("--> END $method (${loggingOutputStream.writeCount()}-byte body)") + System.err.println() + } + + override fun contentType(): String? = body.contentType() + + override fun contentLength(): Long = body.contentLength() + + override fun repeatable(): Boolean = body.repeatable() + + override fun close() = body.close() +} + +/** + * An [OutputStream] wrapper that delegates to [outputStream] while also logging bytes line by line + * as it's written to. + * + * The written content is assumed to be in the given [charset] and the logging occurs in a streaming + * manner with minimal buffering. + */ +private class LoggingOutputStream(private val outputStream: OutputStream, charset: Charset?) : + OutputStream() { + + private val buffer = LoggingBuffer(charset) + + fun writeCount() = buffer.writeCount() + + override fun write(b: Int) { + outputStream.write(b) + buffer.write(b) + } + + override fun write(b: ByteArray, off: Int, len: Int) { + outputStream.write(b, off, len) + for (i in off until off + len) { + buffer.write(b[i].toInt() and 0xFF) + } + } + + /** Prints any currently buffered content. */ + override fun flush() { + buffer.flush() + outputStream.flush() + } + + override fun close() = outputStream.close() +} + +/** + * An [HttpResponse] wrapper that delegates to [response] while also logging line-by-line as it's + * read. + * + * The logging occurs in a streaming manner with minimal buffering. + */ +private class LoggingHttpResponse(private val response: HttpResponse) : HttpResponse { + + private val loggingBody: Lazy = lazy { + LoggingInputStream( + response.body(), + parseCharset(response.headers().values("Content-Type").firstOrNull()), + ) + } + + override fun statusCode(): Int = response.statusCode() + + override fun headers(): Headers = response.headers() + + override fun body(): InputStream = loggingBody.value + + override fun close() { + if (loggingBody.isInitialized()) { + loggingBody.value.close() + } + response.close() + } +} + +/** + * An [InputStream] wrapper that delegates to [inputStream] while also logging bytes line by line as + * it's read. + * + * The contents of [inputStream] are assumed to be in the given [charset] and the logging occurs in + * a streaming manner with minimal buffering. + */ +private class LoggingInputStream(private val inputStream: InputStream, charset: Charset?) : + InputStream() { + + private var isDone = false + private val buffer = LoggingBuffer(charset) + + override fun read(): Int { + if (isDone) { + return -1 + } + + val b = inputStream.read() + + if (b == -1) { + markDone() + return b + } + + buffer.write(b) + return b + } + + override fun read(b: ByteArray, off: Int, len: Int): Int { + if (isDone) { + return -1 + } + + val bytesRead = inputStream.read(b, off, len) + + if (bytesRead == -1) { + markDone() + return bytesRead + } + + for (i in off until off + bytesRead) { + buffer.write(b[i].toInt() and 0xFF) + } + return bytesRead + } + + override fun close() { + if (!isDone) { + markDone(closedEarly = true) + } + inputStream.close() + } + + private fun markDone(closedEarly: Boolean = false) { + isDone = true + buffer.flush() + val suffix = if (closedEarly) ", closed early" else "" + System.err.println("<-- END HTTP (${buffer.writeCount()}-byte body$suffix)") + System.err.println() + } +} + +/** + * A byte buffer that prints line by line, using the given [charset], as bytes are written to it. + * + * When [charset] is `null`, the buffer performs an upfront check to detect binary content. If + * non-whitespace ISO control characters are found in the first [PROBABLY_UTF8_CODE_POINT_LIMIT] + * code points, body logging is suppressed entirely. + */ +private class LoggingBuffer(charset: Charset?) { + + private val charset = charset ?: StandardCharsets.UTF_8 + + private val decoder: CharsetDecoder = + this.charset + .newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT) + private var writeCount = 0 + private val buffer = ByteArrayOutputStream(128) + + /** + * Whether logging has been suppressed because the content doesn't appear to be readable text. + * + * This is only set when [charset] is `null` and the content fails the [isProbablyUtf8] check. + */ + private var suppressed = false + + /** + * Bytes accumulated for the [isProbablyUtf8] check before any lines are printed. + * + * Once the check passes (or [charset] is non-null), this is set to `null` and bytes flow + * directly to [buffer]. + */ + private var prefetchBuffer: ByteArrayOutputStream? = + if (charset != null) null else ByteArrayOutputStream(128) + + fun writeCount() = writeCount + + fun write(b: Int) { + if (writeCount == 0) { + // Print a newline before we start printing anything to separate the printed content + // from previous content. + System.err.println() + } + + writeCount++ + + if (suppressed) { + return + } + + val prefetch = prefetchBuffer + if (prefetch != null) { + prefetch.write(b) + // Continue accumulating until we have enough bytes to decide. + if (prefetch.size() < PROBABLY_UTF8_BYTE_LIMIT && b != '\n'.code) { + return + } + // We have enough bytes. Check if the content is probably UTF-8. + prefetchBuffer = null + val bytes = prefetch.toByteArray() + if (!isProbablyUtf8(bytes)) { + suppressed = true + System.err.println("(binary body omitted)") + return + } + // Content looks like UTF-8. Feed the accumulated bytes into the normal buffer. + for (byte in bytes) { + writeToBuffer(byte.toInt() and 0xFF) + } + return + } + + writeToBuffer(b) + } + + private fun writeToBuffer(b: Int) { + if (b == '\n'.code) { + flush() + return + } + + buffer.write(b) + } + + /** Prints any currently buffered content. */ + fun flush() { + if (suppressed) { + return + } + + // If we still have a prefetch buffer when flush is called (body was shorter than the + // limit), run the check now. + val prefetch = prefetchBuffer + if (prefetch != null) { + prefetchBuffer = null + val bytes = prefetch.toByteArray() + if (bytes.isEmpty()) { + return + } + if (!isProbablyUtf8(bytes)) { + suppressed = true + System.err.println("(binary body omitted)") + return + } + for (byte in bytes) { + writeToBuffer(byte.toInt() and 0xFF) + } + } + + if (buffer.size() == 0) { + return + } + + val line = + try { + decoder.decode(ByteBuffer.wrap(buffer.toByteArray())) + } catch (e: CharacterCodingException) { + "(omitted line is not valid $charset)" + } + buffer.reset() + System.err.println(line) + } +} + +/** The maximum number of code points to sample when checking if content is probably UTF-8. */ +private const val PROBABLY_UTF8_CODE_POINT_LIMIT = 64 + +/** + * The maximum number of bytes to accumulate before running the [isProbablyUtf8] check. UTF-8 code + * points are at most 4 bytes, so this accommodates [PROBABLY_UTF8_CODE_POINT_LIMIT] code points. + */ +private const val PROBABLY_UTF8_BYTE_LIMIT = PROBABLY_UTF8_CODE_POINT_LIMIT * 4 + +/** + * Returns `true` if the given [bytes] probably contain human-readable UTF-8 text. + * + * Decodes up to [PROBABLY_UTF8_CODE_POINT_LIMIT] code points and returns `false` if any + * non-whitespace ISO control characters are found, or if the bytes are not valid UTF-8. + */ +private fun isProbablyUtf8(bytes: ByteArray): Boolean { + try { + val decoder = + StandardCharsets.UTF_8.newDecoder() + .onMalformedInput(CodingErrorAction.REPORT) + .onUnmappableCharacter(CodingErrorAction.REPORT) + val charBuffer = decoder.decode(ByteBuffer.wrap(bytes)) + var codePointCount = 0 + var i = 0 + while (i < charBuffer.length && codePointCount < PROBABLY_UTF8_CODE_POINT_LIMIT) { + val codePoint = Character.codePointAt(charBuffer, i) + if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { + return false + } + i += Character.charCount(codePoint) + codePointCount++ + } + return true + } catch (e: CharacterCodingException) { + return false + } +} + +/** Returns the [Charset] in the given [contentType] string, or `null` if unspecified. */ +private fun parseCharset(contentType: String?): Charset? = + contentType + ?.split(";") + ?.drop(1) + ?.map { it.trim() } + ?.firstOrNull { it.startsWith("charset=", ignoreCase = true) } + ?.substringAfter("=") + ?.trim() + ?.removeSurrounding("\"") + ?.let { runCatching { charset(it) }.getOrNull() } + +/** Formats the [Duration] into a string like "1m 40s 467ms". */ +private fun Duration.format(): String = + toKotlinDuration().toComponents { days, hours, minutes, seconds, nanoseconds -> + buildString { + val milliseconds = nanoseconds / 1_000_000 + if (days > 0) { + append("${days}d") + } + if (hours > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${hours}h") + } + if (minutes > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${minutes}m") + } + if (seconds > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${seconds}s") + } + if (milliseconds > 0) { + if (isNotEmpty()) { + append(" ") + } + append("${milliseconds}ms") + } + + if (isEmpty()) { + append("0s") + } + } + } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/ProxyAuthenticator.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/ProxyAuthenticator.kt new file mode 100644 index 000000000..7f4bcb93c --- /dev/null +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/ProxyAuthenticator.kt @@ -0,0 +1,59 @@ +package com.tryfinch.api.core.http + +import java.net.Proxy +import java.nio.charset.Charset +import java.nio.charset.StandardCharsets +import java.util.Base64 +import java.util.Optional + +/** + * Provides credentials when an HTTP proxy responds with `407 Proxy Authentication Required`. + * + * Implementations inspect the 407 [response] (typically its `Proxy-Authenticate` header) and return + * the request to retry with a `Proxy-Authorization` header set, or [Optional.empty] to abandon + * authentication and surface the 407 to the caller. + * + * Implementations must be thread-safe; they may be invoked concurrently from multiple HTTP calls. + */ +fun interface ProxyAuthenticator { + + /** + * @param proxy the proxy that produced the challenge, or [Proxy.NO_PROXY] if the route is not + * yet established + * @param request the request that produced [response] + * @param response the 407 challenge response + * @return the retry request to send (typically [request] with a `Proxy-Authorization` header + * added), or [Optional.empty] to abandon authentication + */ + fun authenticate( + proxy: Proxy, + request: HttpRequest, + response: HttpResponse, + ): Optional + + companion object { + + /** + * A [ProxyAuthenticator] that uses RFC 7617 Basic authentication with the ISO-8859-1 + * charset. + */ + @JvmStatic + fun basic(username: String, password: String): ProxyAuthenticator = + basic(username, password, StandardCharsets.ISO_8859_1) + + /** + * A [ProxyAuthenticator] that uses RFC 7617 Basic authentication with the given [charset]. + */ + @JvmStatic + fun basic(username: String, password: String, charset: Charset): ProxyAuthenticator { + val token = + Base64.getEncoder().encodeToString("$username:$password".toByteArray(charset)) + val headerValue = "Basic $token" + return ProxyAuthenticator { _, request, _ -> + Optional.of( + request.toBuilder().putHeader("Proxy-Authorization", headerValue).build() + ) + } + } + } +} diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/RetryingHttpClient.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/RetryingHttpClient.kt index 65179d582..a2b202750 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/RetryingHttpClient.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/core/http/RetryingHttpClient.kt @@ -1,3 +1,5 @@ +// File generated from our OpenAPI spec by Stainless. + package com.tryfinch.api.core.http import com.tryfinch.api.core.DefaultSleeper @@ -199,7 +201,7 @@ private constructor( ?: headers.values("Retry-After").getOrNull(0)?.let { retryAfter -> retryAfter.toFloatOrNull()?.times(TimeUnit.SECONDS.toNanos(1)) ?: try { - ChronoUnit.MILLIS.between( + ChronoUnit.NANOS.between( OffsetDateTime.now(clock), OffsetDateTime.parse( retryAfter, @@ -212,13 +214,8 @@ private constructor( } } ?.let { retryAfterNanos -> - // If the API asks us to wait a certain amount of time (and it's a reasonable - // amount), just - // do what it says. - val retryAfter = Duration.ofNanos(retryAfterNanos.toLong()) - if (retryAfter in Duration.ofNanos(0)..Duration.ofMinutes(1)) { - return retryAfter - } + // If the API asks us to wait a certain amount of time, do what it says. + return Duration.ofNanos(retryAfterNanos.toLong()) } // Apply exponential backoff, but not more than the max. diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/BadRequestException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/BadRequestException.kt index 6b42dcad7..afff15699 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/BadRequestException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/BadRequestException.kt @@ -5,12 +5,16 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class BadRequestException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - FinchServiceException("400: $body", cause) { + FinchServiceException( + "400: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 400 diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/InternalServerException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/InternalServerException.kt index 0e432de35..b6fed6e6d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/InternalServerException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/InternalServerException.kt @@ -5,6 +5,7 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,7 +15,11 @@ private constructor( private val headers: Headers, private val body: JsonValue, cause: Throwable?, -) : FinchServiceException("$statusCode: $body", cause) { +) : + FinchServiceException( + "$statusCode: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = statusCode diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/NotFoundException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/NotFoundException.kt index 78219c0c6..62c4dbaa3 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/NotFoundException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/NotFoundException.kt @@ -5,12 +5,16 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class NotFoundException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - FinchServiceException("404: $body", cause) { + FinchServiceException( + "404: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 404 diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/PermissionDeniedException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/PermissionDeniedException.kt index b43c0875e..c796d3d8e 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/PermissionDeniedException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/PermissionDeniedException.kt @@ -5,12 +5,16 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class PermissionDeniedException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - FinchServiceException("403: $body", cause) { + FinchServiceException( + "403: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 403 diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/RateLimitException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/RateLimitException.kt index 02907cfc4..4e44f0148 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/RateLimitException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/RateLimitException.kt @@ -5,12 +5,16 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class RateLimitException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - FinchServiceException("429: $body", cause) { + FinchServiceException( + "429: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 429 diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnauthorizedException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnauthorizedException.kt index 91143b9dc..f85192d08 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnauthorizedException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnauthorizedException.kt @@ -5,12 +5,16 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class UnauthorizedException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - FinchServiceException("401: $body", cause) { + FinchServiceException( + "401: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 401 diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnexpectedStatusCodeException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnexpectedStatusCodeException.kt index 5d89680bd..ec90a1a69 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnexpectedStatusCodeException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnexpectedStatusCodeException.kt @@ -5,6 +5,7 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull @@ -14,7 +15,11 @@ private constructor( private val headers: Headers, private val body: JsonValue, cause: Throwable?, -) : FinchServiceException("$statusCode: $body", cause) { +) : + FinchServiceException( + "$statusCode: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = statusCode diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnprocessableEntityException.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnprocessableEntityException.kt index c937818a1..3963339db 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnprocessableEntityException.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/errors/UnprocessableEntityException.kt @@ -5,12 +5,16 @@ package com.tryfinch.api.errors import com.tryfinch.api.core.JsonValue import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.http.Headers +import com.tryfinch.api.core.jsonMapper import java.util.Optional import kotlin.jvm.optionals.getOrNull class UnprocessableEntityException private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : - FinchServiceException("422: $body", cause) { + FinchServiceException( + "422: ${if (body.isMissing()) "Unknown" else jsonMapper().writeValueAsString(body)}", + cause, + ) { override fun statusCode(): Int = 422 diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccessTokenCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccessTokenCreateParams.kt index 75ba86fdd..a77964ea2 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccessTokenCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccessTokenCreateParams.kt @@ -554,6 +554,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CreateAccessTokenRequest = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountCreateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountCreateResponse.kt index abb928369..372f29732 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountCreateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountCreateResponse.kt @@ -420,6 +420,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): AccountCreateResponse = apply { if (validated) { return@apply @@ -563,6 +571,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateEvent.kt index 1faf0298f..21788eca4 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateEvent.kt @@ -24,6 +24,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -36,17 +37,19 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -75,6 +78,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -116,6 +127,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -162,6 +180,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -171,6 +190,7 @@ private constructor( accountId = accountUpdateEvent.accountId companyId = accountUpdateEvent.companyId connectionId = accountUpdateEvent.connectionId + entityId = accountUpdateEvent.entityId data = accountUpdateEvent.data eventType = accountUpdateEvent.eventType additionalProperties = accountUpdateEvent.additionalProperties.toMutableMap() @@ -224,6 +244,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: Data) = data(JsonField.of(data)) /** @@ -282,6 +313,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -290,6 +322,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): AccountUpdateEvent = apply { if (validated) { return@apply @@ -298,6 +338,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -321,6 +362,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -482,6 +524,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -716,6 +767,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationMethod = apply { if (validated) { return@apply @@ -1095,6 +1156,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): SupportedFields = apply { if (validated) { return@apply @@ -1543,6 +1614,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): SupportedCompanyFields = apply { if (validated) { return@apply @@ -1860,6 +1941,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Accounts = apply { if (validated) { return@apply @@ -2067,6 +2158,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Departments = apply { if (validated) { return@apply @@ -2207,6 +2308,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API + * for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Parent = apply { if (validated) { return@apply @@ -2415,6 +2526,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Entity = apply { if (validated) { return@apply @@ -2750,6 +2871,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Locations = apply { if (validated) { return@apply @@ -3010,6 +3141,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): SupportedDirectoryFields = apply { if (validated) { return@apply @@ -3377,6 +3518,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Individuals = apply { if (validated) { return@apply @@ -3525,6 +3676,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API + * for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Manager = apply { if (validated) { return@apply @@ -3747,6 +3908,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Paging = apply { if (validated) { return@apply @@ -4522,6 +4693,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): SupportedEmploymentFields = apply { if (validated) { return@apply @@ -4689,6 +4870,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -4878,6 +5069,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Employment = apply { if (validated) { return@apply @@ -5102,6 +5303,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Income = apply { if (validated) { return@apply @@ -5439,6 +5650,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Location = apply { if (validated) { return@apply @@ -5614,6 +5835,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Manager = apply { if (validated) { return@apply @@ -6265,6 +6496,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): SupportedIndividualFields = apply { if (validated) { return@apply @@ -6453,6 +6694,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Emails = apply { if (validated) { return@apply @@ -6642,6 +6893,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): PhoneNumbers = apply { if (validated) { return@apply @@ -6977,6 +7238,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Residence = apply { if (validated) { return@apply @@ -7313,6 +7584,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): SupportedPayGroupFields = apply { if (validated) { return@apply @@ -7521,6 +7802,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): SupportedPayStatementFields = apply { if (validated) { return@apply @@ -7711,6 +8002,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Paging = apply { if (validated) { return@apply @@ -8221,6 +8522,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): PayStatements = apply { if (validated) { return@apply @@ -8486,6 +8797,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API + * for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Earnings = apply { if (validated) { return@apply @@ -8798,6 +9119,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API + * for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): EmployeeDeductions = apply { if (validated) { return@apply @@ -9052,6 +9383,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API + * for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): EmployerContributions = apply { if (validated) { return@apply @@ -9360,6 +9701,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API + * for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Taxes = apply { if (validated) { return@apply @@ -10015,6 +10366,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ fun validate(): SupportedPaymentFields = apply { if (validated) { return@apply @@ -10210,6 +10571,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): PayPeriod = apply { if (validated) { return@apply @@ -10451,6 +10822,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -10614,6 +10995,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -10661,17 +11051,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "AccountUpdateEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "AccountUpdateEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateResponse.kt index bfff64e8c..366c1f01d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AccountUpdateResponse.kt @@ -384,6 +384,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): AccountUpdateResponse = apply { if (validated) { return@apply @@ -525,6 +533,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedAsyncJob.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedAsyncJob.kt index cdcb6c77b..59260e253 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedAsyncJob.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedAsyncJob.kt @@ -456,6 +456,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): AutomatedAsyncJob = apply { if (validated) { return@apply @@ -604,6 +612,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Params = apply { if (validated) { return@apply @@ -758,6 +775,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply @@ -883,6 +909,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedCreateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedCreateResponse.kt index a01a4d5c0..77f6a78f8 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedCreateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedCreateResponse.kt @@ -275,6 +275,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): AutomatedCreateResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedListResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedListResponse.kt index b9a02fdcc..619c0cae6 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedListResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/AutomatedListResponse.kt @@ -178,6 +178,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): AutomatedListResponse = apply { if (validated) { return@apply @@ -310,6 +318,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Meta = apply { if (validated) { return@apply @@ -445,6 +462,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Quotas = apply { if (validated) { return@apply @@ -620,6 +647,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): DataSyncAll = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BaseWebhookEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BaseWebhookEvent.kt index a3c5d0cd9..edbf92245 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BaseWebhookEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BaseWebhookEvent.kt @@ -22,6 +22,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val additionalProperties: MutableMap, ) { @@ -32,7 +33,8 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, mutableMapOf()) + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), + ) : this(accountId, companyId, connectionId, entityId, mutableMapOf()) /** * [DEPRECATED] Unique Finch ID of the employer account used to make this connection. Use @@ -60,6 +62,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * Returns the raw JSON value of [accountId]. * @@ -89,6 +99,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -121,6 +138,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -128,6 +146,7 @@ private constructor( accountId = baseWebhookEvent.accountId companyId = baseWebhookEvent.companyId connectionId = baseWebhookEvent.connectionId + entityId = baseWebhookEvent.entityId additionalProperties = baseWebhookEvent.additionalProperties.toMutableMap() } @@ -179,6 +198,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -216,12 +246,21 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, additionalProperties.toMutableMap(), ) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): BaseWebhookEvent = apply { if (validated) { return@apply @@ -230,6 +269,7 @@ private constructor( accountId() companyId() connectionId() + entityId() validated = true } @@ -250,7 +290,8 @@ private constructor( internal fun validity(): Int = (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + - (if (connectionId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) override fun equals(other: Any?): Boolean { if (this === other) { @@ -261,15 +302,16 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, additionalProperties) + Objects.hash(accountId, companyId, connectionId, entityId, additionalProperties) } override fun hashCode(): Int = hashCode override fun toString() = - "BaseWebhookEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, additionalProperties=$additionalProperties}" + "BaseWebhookEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitContribution.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitContribution.kt index b2f29efaa..0f4883eee 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitContribution.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitContribution.kt @@ -35,42 +35,79 @@ import kotlin.jvm.optionals.getOrNull @JsonSerialize(using = BenefitContribution.Serializer::class) class BenefitContribution private constructor( - private val unionMember0: UnionMember0? = null, - private val unionMember1: UnionMember1? = null, - private val unionMember2: UnionMember2? = null, + private val fixed: BenefitContributionFixed? = null, + private val percent: BenefitContributionPercent? = null, + private val tiered: BenefitContributionTiered? = null, private val _json: JsonValue? = null, ) { - fun unionMember0(): Optional = Optional.ofNullable(unionMember0) + fun fixed(): Optional = Optional.ofNullable(fixed) - fun unionMember1(): Optional = Optional.ofNullable(unionMember1) + fun percent(): Optional = Optional.ofNullable(percent) - fun unionMember2(): Optional = Optional.ofNullable(unionMember2) + fun tiered(): Optional = Optional.ofNullable(tiered) - fun isUnionMember0(): Boolean = unionMember0 != null + fun isFixed(): Boolean = fixed != null - fun isUnionMember1(): Boolean = unionMember1 != null + fun isPercent(): Boolean = percent != null - fun isUnionMember2(): Boolean = unionMember2 != null + fun isTiered(): Boolean = tiered != null - fun asUnionMember0(): UnionMember0 = unionMember0.getOrThrow("unionMember0") + fun asFixed(): BenefitContributionFixed = fixed.getOrThrow("fixed") - fun asUnionMember1(): UnionMember1 = unionMember1.getOrThrow("unionMember1") + fun asPercent(): BenefitContributionPercent = percent.getOrThrow("percent") - fun asUnionMember2(): UnionMember2 = unionMember2.getOrThrow("unionMember2") + fun asTiered(): BenefitContributionTiered = tiered.getOrThrow("tiered") fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = benefitContribution.accept(new BenefitContribution.Visitor>() { + * @Override + * public Optional visitFixed(BenefitContributionFixed fixed) { + * return Optional.of(fixed.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and the + * current variant is unknown. + */ fun accept(visitor: Visitor): T = when { - unionMember0 != null -> visitor.visitUnionMember0(unionMember0) - unionMember1 != null -> visitor.visitUnionMember1(unionMember1) - unionMember2 != null -> visitor.visitUnionMember2(unionMember2) + fixed != null -> visitor.visitFixed(fixed) + percent != null -> visitor.visitPercent(percent) + tiered != null -> visitor.visitTiered(tiered) else -> visitor.unknown(_json) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): BenefitContribution = apply { if (validated) { return@apply @@ -78,16 +115,16 @@ private constructor( accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) { - unionMember0.validate() + override fun visitFixed(fixed: BenefitContributionFixed) { + fixed.validate() } - override fun visitUnionMember1(unionMember1: UnionMember1) { - unionMember1.validate() + override fun visitPercent(percent: BenefitContributionPercent) { + percent.validate() } - override fun visitUnionMember2(unionMember2: UnionMember2) { - unionMember2.validate() + override fun visitTiered(tiered: BenefitContributionTiered) { + tiered.validate() } } ) @@ -111,11 +148,11 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) = unionMember0.validity() + override fun visitFixed(fixed: BenefitContributionFixed) = fixed.validity() - override fun visitUnionMember1(unionMember1: UnionMember1) = unionMember1.validity() + override fun visitPercent(percent: BenefitContributionPercent) = percent.validity() - override fun visitUnionMember2(unionMember2: UnionMember2) = unionMember2.validity() + override fun visitTiered(tiered: BenefitContributionTiered) = tiered.validity() override fun unknown(json: JsonValue?) = 0 } @@ -127,35 +164,31 @@ private constructor( } return other is BenefitContribution && - unionMember0 == other.unionMember0 && - unionMember1 == other.unionMember1 && - unionMember2 == other.unionMember2 + fixed == other.fixed && + percent == other.percent && + tiered == other.tiered } - override fun hashCode(): Int = Objects.hash(unionMember0, unionMember1, unionMember2) + override fun hashCode(): Int = Objects.hash(fixed, percent, tiered) override fun toString(): String = when { - unionMember0 != null -> "BenefitContribution{unionMember0=$unionMember0}" - unionMember1 != null -> "BenefitContribution{unionMember1=$unionMember1}" - unionMember2 != null -> "BenefitContribution{unionMember2=$unionMember2}" + fixed != null -> "BenefitContribution{fixed=$fixed}" + percent != null -> "BenefitContribution{percent=$percent}" + tiered != null -> "BenefitContribution{tiered=$tiered}" _json != null -> "BenefitContribution{_unknown=$_json}" else -> throw IllegalStateException("Invalid BenefitContribution") } companion object { - @JvmStatic - fun ofUnionMember0(unionMember0: UnionMember0) = - BenefitContribution(unionMember0 = unionMember0) + @JvmStatic fun ofFixed(fixed: BenefitContributionFixed) = BenefitContribution(fixed = fixed) @JvmStatic - fun ofUnionMember1(unionMember1: UnionMember1) = - BenefitContribution(unionMember1 = unionMember1) + fun ofPercent(percent: BenefitContributionPercent) = BenefitContribution(percent = percent) @JvmStatic - fun ofUnionMember2(unionMember2: UnionMember2) = - BenefitContribution(unionMember2 = unionMember2) + fun ofTiered(tiered: BenefitContributionTiered) = BenefitContribution(tiered = tiered) } /** @@ -164,11 +197,11 @@ private constructor( */ interface Visitor { - fun visitUnionMember0(unionMember0: UnionMember0): T + fun visitFixed(fixed: BenefitContributionFixed): T - fun visitUnionMember1(unionMember1: UnionMember1): T + fun visitPercent(percent: BenefitContributionPercent): T - fun visitUnionMember2(unionMember2: UnionMember2): T + fun visitTiered(tiered: BenefitContributionTiered): T /** * Maps an unknown variant of [BenefitContribution] to a value of type [T]. @@ -193,14 +226,14 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - BenefitContribution(unionMember0 = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + BenefitContribution(fixed = it, _json = json) }, - tryDeserialize(node, jacksonTypeRef())?.let { - BenefitContribution(unionMember1 = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + BenefitContribution(percent = it, _json = json) }, - tryDeserialize(node, jacksonTypeRef())?.let { - BenefitContribution(unionMember2 = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + BenefitContribution(tiered = it, _json = json) }, ) .filterNotNull() @@ -226,16 +259,16 @@ private constructor( provider: SerializerProvider, ) { when { - value.unionMember0 != null -> generator.writeObject(value.unionMember0) - value.unionMember1 != null -> generator.writeObject(value.unionMember1) - value.unionMember2 != null -> generator.writeObject(value.unionMember2) + value.fixed != null -> generator.writeObject(value.fixed) + value.percent != null -> generator.writeObject(value.percent) + value.tiered != null -> generator.writeObject(value.tiered) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid BenefitContribution") } } } - class UnionMember0 + class BenefitContributionFixed @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, @@ -294,7 +327,7 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember0]. + * Returns a mutable builder for constructing an instance of [BenefitContributionFixed]. * * The following fields are required: * ```java @@ -305,7 +338,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember0]. */ + /** A builder for [BenefitContributionFixed]. */ class Builder internal constructor() { private var amount: JsonField? = null @@ -313,10 +346,10 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(unionMember0: UnionMember0) = apply { - amount = unionMember0.amount - type = unionMember0.type - additionalProperties = unionMember0.additionalProperties.toMutableMap() + internal fun from(benefitContributionFixed: BenefitContributionFixed) = apply { + amount = benefitContributionFixed.amount + type = benefitContributionFixed.type + additionalProperties = benefitContributionFixed.additionalProperties.toMutableMap() } /** Contribution amount in cents. */ @@ -363,7 +396,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember0]. + * Returns an immutable instance of [BenefitContributionFixed]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -375,8 +408,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember0 = - UnionMember0( + fun build(): BenefitContributionFixed = + BenefitContributionFixed( checkRequired("amount", amount), checkRequired("type", type), additionalProperties.toMutableMap(), @@ -385,7 +418,16 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember0 = apply { + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): BenefitContributionFixed = apply { if (validated) { return@apply } @@ -498,6 +540,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -541,7 +593,7 @@ private constructor( return true } - return other is UnionMember0 && + return other is BenefitContributionFixed && amount == other.amount && type == other.type && additionalProperties == other.additionalProperties @@ -552,10 +604,10 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember0{amount=$amount, type=$type, additionalProperties=$additionalProperties}" + "BenefitContributionFixed{amount=$amount, type=$type, additionalProperties=$additionalProperties}" } - class UnionMember1 + class BenefitContributionPercent @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, @@ -614,7 +666,8 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember1]. + * Returns a mutable builder for constructing an instance of + * [BenefitContributionPercent]. * * The following fields are required: * ```java @@ -625,7 +678,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember1]. */ + /** A builder for [BenefitContributionPercent]. */ class Builder internal constructor() { private var amount: JsonField? = null @@ -633,10 +686,11 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(unionMember1: UnionMember1) = apply { - amount = unionMember1.amount - type = unionMember1.type - additionalProperties = unionMember1.additionalProperties.toMutableMap() + internal fun from(benefitContributionPercent: BenefitContributionPercent) = apply { + amount = benefitContributionPercent.amount + type = benefitContributionPercent.type + additionalProperties = + benefitContributionPercent.additionalProperties.toMutableMap() } /** Contribution amount in basis points (1/100th of a percent). */ @@ -683,7 +737,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember1]. + * Returns an immutable instance of [BenefitContributionPercent]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -695,8 +749,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember1 = - UnionMember1( + fun build(): BenefitContributionPercent = + BenefitContributionPercent( checkRequired("amount", amount), checkRequired("type", type), additionalProperties.toMutableMap(), @@ -705,7 +759,16 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember1 = apply { + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): BenefitContributionPercent = apply { if (validated) { return@apply } @@ -818,6 +881,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -861,7 +934,7 @@ private constructor( return true } - return other is UnionMember1 && + return other is BenefitContributionPercent && amount == other.amount && type == other.type && additionalProperties == other.additionalProperties @@ -872,10 +945,10 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember1{amount=$amount, type=$type, additionalProperties=$additionalProperties}" + "BenefitContributionPercent{amount=$amount, type=$type, additionalProperties=$additionalProperties}" } - class UnionMember2 + class BenefitContributionTiered @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val tiers: JsonField>, @@ -935,7 +1008,8 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember2]. + * Returns a mutable builder for constructing an instance of + * [BenefitContributionTiered]. * * The following fields are required: * ```java @@ -946,7 +1020,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember2]. */ + /** A builder for [BenefitContributionTiered]. */ class Builder internal constructor() { private var tiers: JsonField>? = null @@ -954,10 +1028,10 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(unionMember2: UnionMember2) = apply { - tiers = unionMember2.tiers.map { it.toMutableList() } - type = unionMember2.type - additionalProperties = unionMember2.additionalProperties.toMutableMap() + internal fun from(benefitContributionTiered: BenefitContributionTiered) = apply { + tiers = benefitContributionTiered.tiers.map { it.toMutableList() } + type = benefitContributionTiered.type + additionalProperties = benefitContributionTiered.additionalProperties.toMutableMap() } /** @@ -1021,7 +1095,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember2]. + * Returns an immutable instance of [BenefitContributionTiered]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -1033,8 +1107,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember2 = - UnionMember2( + fun build(): BenefitContributionTiered = + BenefitContributionTiered( checkRequired("tiers", tiers).map { it.toImmutable() }, checkRequired("type", type), additionalProperties.toMutableMap(), @@ -1043,7 +1117,16 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember2 = apply { + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): BenefitContributionTiered = apply { if (validated) { return@apply } @@ -1224,6 +1307,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tier = apply { if (validated) { return@apply @@ -1358,6 +1451,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1401,7 +1504,7 @@ private constructor( return true } - return other is UnionMember2 && + return other is BenefitContributionTiered && tiers == other.tiers && type == other.type && additionalProperties == other.additionalProperties @@ -1412,6 +1515,6 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember2{tiers=$tiers, type=$type, additionalProperties=$additionalProperties}" + "BenefitContributionTiered{tiers=$tiers, type=$type, additionalProperties=$additionalProperties}" } } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFeaturesAndOperations.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFeaturesAndOperations.kt index 665a11a54..cec233cc8 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFeaturesAndOperations.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFeaturesAndOperations.kt @@ -164,6 +164,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): BenefitFeaturesAndOperations = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFrequency.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFrequency.kt index e6bdb44f8..9892ac835 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFrequency.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitFrequency.kt @@ -102,6 +102,14 @@ class BenefitFrequency @JsonCreator private constructor(private val value: JsonF private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): BenefitFrequency = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitType.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitType.kt index e7edd4239..693069ac0 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitType.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitType.kt @@ -195,6 +195,14 @@ class BenefitType @JsonCreator private constructor(private val value: JsonField< private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): BenefitType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitsSupport.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitsSupport.kt index afd9845f0..e62d66db6 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitsSupport.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/BenefitsSupport.kt @@ -579,6 +579,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): BenefitsSupport = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Company.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Company.kt index 96420583e..805544392 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Company.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Company.kt @@ -513,6 +513,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Company = apply { if (validated) { return@apply @@ -873,6 +881,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Account = apply { if (validated) { return@apply @@ -1002,6 +1019,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AccountType = apply { if (validated) { return@apply @@ -1227,6 +1254,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -1376,6 +1412,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Parent = apply { if (validated) { return@apply @@ -1595,6 +1641,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Entity = apply { if (validated) { return@apply @@ -1723,6 +1778,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Subtype = apply { if (validated) { return@apply @@ -1881,6 +1946,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyBenefit.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyBenefit.kt index 911be02d4..4fe83d284 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyBenefit.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyBenefit.kt @@ -299,6 +299,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): CompanyBenefit = apply { if (validated) { return@apply @@ -495,6 +503,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BenefitCompanyMatchContribution = apply { if (validated) { return@apply @@ -676,6 +693,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tier = apply { if (validated) { return@apply @@ -809,6 +836,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyEvent.kt index e7b74a609..35806ffc0 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyEvent.kt @@ -25,6 +25,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -37,17 +38,19 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -76,6 +79,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -117,6 +128,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -163,6 +181,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -172,6 +191,7 @@ private constructor( accountId = companyEvent.accountId companyId = companyEvent.companyId connectionId = companyEvent.connectionId + entityId = companyEvent.entityId data = companyEvent.data eventType = companyEvent.eventType additionalProperties = companyEvent.additionalProperties.toMutableMap() @@ -225,6 +245,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: Data?) = data(JsonField.ofNullable(data)) /** Alias for calling [Builder.data] with `data.orElse(null)`. */ @@ -286,6 +317,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -294,6 +326,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): CompanyEvent = apply { if (validated) { return@apply @@ -302,6 +342,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -325,6 +366,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -386,6 +428,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -509,6 +560,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -556,17 +616,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "CompanyEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "CompanyEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyUpdateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyUpdateResponse.kt index 96ed910cf..8cc68b505 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyUpdateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CompanyUpdateResponse.kt @@ -479,6 +479,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): CompanyUpdateResponse = apply { if (validated) { return@apply @@ -815,6 +823,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Account = apply { if (validated) { return@apply @@ -944,6 +961,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AccountType = apply { if (validated) { return@apply @@ -1148,6 +1175,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -1282,6 +1318,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Parent = apply { if (validated) { return@apply @@ -1480,6 +1526,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Entity = apply { if (validated) { return@apply @@ -1608,6 +1663,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Subtype = apply { if (validated) { return@apply @@ -1766,6 +1831,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionNewParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionNewParams.kt index 3522aae4b..9aba999db 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionNewParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionNewParams.kt @@ -48,7 +48,9 @@ private constructor( fun customerName(): String = body.customerName() /** - * The Finch products to request access to + * The Finch products to request access to. Use `benefits` to access deductions endpoints — + * `deduction` is a deprecated alias that is still accepted but should not be combined with + * `benefits`. * * @throws FinchInvalidDataException if the JSON field has an unexpected type or is unexpectedly * missing or null (e.g. if the server responded with an unexpected value). @@ -246,7 +248,11 @@ private constructor( body.customerName(customerName) } - /** The Finch products to request access to */ + /** + * The Finch products to request access to. Use `benefits` to access deductions endpoints — + * `deduction` is a deprecated alias that is still accepted but should not be combined with + * `benefits`. + */ fun products(products: List) = apply { body.products(products) } /** @@ -594,7 +600,9 @@ private constructor( fun customerName(): String = customerName.getRequired("customer_name") /** - * The Finch products to request access to + * The Finch products to request access to. Use `benefits` to access deductions endpoints — + * `deduction` is a deprecated alias that is still accepted but should not be combined with + * `benefits`. * * @throws FinchInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). @@ -812,7 +820,11 @@ private constructor( this.customerName = customerName } - /** The Finch products to request access to */ + /** + * The Finch products to request access to. Use `benefits` to access deductions + * endpoints — `deduction` is a deprecated alias that is still accepted but should not + * be combined with `benefits`. + */ fun products(products: List) = products(JsonField.of(products)) /** @@ -1010,6 +1022,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CreateConnectSessionRequest = apply { if (validated) { return@apply @@ -1092,7 +1113,6 @@ private constructor( "CreateConnectSessionRequest{customerId=$customerId, customerName=$customerName, products=$products, customerEmail=$customerEmail, integration=$integration, manual=$manual, minutesToExpire=$minutesToExpire, redirectUri=$redirectUri, sandbox=$sandbox, additionalProperties=$additionalProperties}" } - /** The Finch products that can be requested during the Connect flow. */ class ConnectProducts @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -1231,6 +1251,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ConnectProducts = apply { if (validated) { return@apply @@ -1429,6 +1458,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Integration = apply { if (validated) { return@apply @@ -1564,6 +1602,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthMethod = apply { if (validated) { return@apply @@ -1710,6 +1758,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Sandbox = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionReauthenticateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionReauthenticateParams.kt index 78984af0d..1dbaad120 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionReauthenticateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectSessionReauthenticateParams.kt @@ -48,7 +48,9 @@ private constructor( fun minutesToExpire(): Optional = body.minutesToExpire() /** - * The products to request access to (optional for reauthentication) + * The products to request access to (optional for reauthentication). Use `benefits` to access + * deductions endpoints — `deduction` is a deprecated alias that is still accepted but should + * not be combined with `benefits`. * * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -173,7 +175,11 @@ private constructor( body.minutesToExpire(minutesToExpire) } - /** The products to request access to (optional for reauthentication) */ + /** + * The products to request access to (optional for reauthentication). Use `benefits` to + * access deductions endpoints — `deduction` is a deprecated alias that is still accepted + * but should not be combined with `benefits`. + */ fun products(products: List?) = apply { body.products(products) } /** Alias for calling [Builder.products] with `products.orElse(null)`. */ @@ -396,7 +402,9 @@ private constructor( fun minutesToExpire(): Optional = minutesToExpire.getOptional("minutes_to_expire") /** - * The products to request access to (optional for reauthentication) + * The products to request access to (optional for reauthentication). Use `benefits` to + * access deductions endpoints — `deduction` is a deprecated alias that is still accepted + * but should not be combined with `benefits`. * * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -524,7 +532,11 @@ private constructor( this.minutesToExpire = minutesToExpire } - /** The products to request access to (optional for reauthentication) */ + /** + * The products to request access to (optional for reauthentication). Use `benefits` to + * access deductions endpoints — `deduction` is a deprecated alias that is still + * accepted but should not be combined with `benefits`. + */ fun products(products: List?) = products(JsonField.ofNullable(products)) @@ -614,6 +626,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ReauthenticateRequest = apply { if (validated) { return@apply @@ -670,7 +691,6 @@ private constructor( "ReauthenticateRequest{connectionId=$connectionId, minutesToExpire=$minutesToExpire, products=$products, redirectUri=$redirectUri, additionalProperties=$additionalProperties}" } - /** The Finch products that can be requested during the Connect flow. */ class ConnectProducts @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -809,6 +829,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ConnectProducts = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionCreateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionCreateResponse.kt index 6845fb4dc..2b1f38d26 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionCreateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionCreateResponse.kt @@ -451,6 +451,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): ConnectionCreateResponse = apply { if (validated) { return@apply @@ -596,6 +604,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionStatusType.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionStatusType.kt index d6b4b286d..b87bf4727 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionStatusType.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ConnectionStatusType.kt @@ -120,6 +120,14 @@ class ConnectionStatusType @JsonCreator private constructor(private val value: J private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): ConnectionStatusType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateAccessTokenResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateAccessTokenResponse.kt index 64a9d8b98..f96a1d983 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateAccessTokenResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateAccessTokenResponse.kt @@ -34,6 +34,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val customerId: JsonField, + private val customerName: JsonField, private val additionalProperties: MutableMap, ) { @@ -66,6 +67,9 @@ private constructor( @JsonProperty("customer_id") @ExcludeMissing customerId: JsonField = JsonMissing.of(), + @JsonProperty("customer_name") + @ExcludeMissing + customerName: JsonField = JsonMissing.of(), ) : this( accessToken, clientType, @@ -78,6 +82,7 @@ private constructor( accountId, companyId, customerId, + customerName, mutableMapOf(), ) @@ -174,6 +179,15 @@ private constructor( */ fun customerId(): Optional = customerId.getOptional("customer_id") + /** + * The name of your customer you provided to Finch when a connect session was created for this + * connection + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun customerName(): Optional = customerName.getOptional("customer_name") + /** * Returns the raw JSON value of [accessToken]. * @@ -267,6 +281,15 @@ private constructor( */ @JsonProperty("customer_id") @ExcludeMissing fun _customerId(): JsonField = customerId + /** + * Returns the raw JSON value of [customerName]. + * + * Unlike [customerName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("customer_name") + @ExcludeMissing + fun _customerName(): JsonField = customerName + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -313,6 +336,7 @@ private constructor( private var accountId: JsonField = JsonMissing.of() private var companyId: JsonField = JsonMissing.of() private var customerId: JsonField = JsonMissing.of() + private var customerName: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -328,6 +352,7 @@ private constructor( accountId = createAccessTokenResponse.accountId companyId = createAccessTokenResponse.companyId customerId = createAccessTokenResponse.customerId + customerName = createAccessTokenResponse.customerName additionalProperties = createAccessTokenResponse.additionalProperties.toMutableMap() } @@ -514,6 +539,26 @@ private constructor( */ fun customerId(customerId: JsonField) = apply { this.customerId = customerId } + /** + * The name of your customer you provided to Finch when a connect session was created for + * this connection + */ + fun customerName(customerName: String?) = customerName(JsonField.ofNullable(customerName)) + + /** Alias for calling [Builder.customerName] with `customerName.orElse(null)`. */ + fun customerName(customerName: Optional) = customerName(customerName.getOrNull()) + + /** + * Sets [Builder.customerName] to an arbitrary JSON value. + * + * You should usually call [Builder.customerName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun customerName(customerName: JsonField) = apply { + this.customerName = customerName + } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -565,12 +610,21 @@ private constructor( accountId, companyId, customerId, + customerName, additionalProperties.toMutableMap(), ) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): CreateAccessTokenResponse = apply { if (validated) { return@apply @@ -587,6 +641,7 @@ private constructor( accountId() companyId() customerId() + customerName() validated = true } @@ -615,7 +670,8 @@ private constructor( (if (tokenType.asKnown().isPresent) 1 else 0) + (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + - (if (customerId.asKnown().isPresent) 1 else 0) + (if (customerId.asKnown().isPresent) 1 else 0) + + (if (customerName.asKnown().isPresent) 1 else 0) /** The type of application associated with a token. */ class ClientType @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -712,6 +768,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ClientType = apply { if (validated) { return@apply @@ -845,6 +910,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ConnectionType = apply { if (validated) { return@apply @@ -900,6 +974,7 @@ private constructor( accountId == other.accountId && companyId == other.companyId && customerId == other.customerId && + customerName == other.customerName && additionalProperties == other.additionalProperties } @@ -916,6 +991,7 @@ private constructor( accountId, companyId, customerId, + customerName, additionalProperties, ) } @@ -923,5 +999,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "CreateAccessTokenResponse{accessToken=$accessToken, clientType=$clientType, connectionId=$connectionId, connectionType=$connectionType, entityIds=$entityIds, products=$products, providerId=$providerId, tokenType=$tokenType, accountId=$accountId, companyId=$companyId, customerId=$customerId, additionalProperties=$additionalProperties}" + "CreateAccessTokenResponse{accessToken=$accessToken, clientType=$clientType, connectionId=$connectionId, connectionType=$connectionType, entityIds=$entityIds, products=$products, providerId=$providerId, tokenType=$tokenType, accountId=$accountId, companyId=$companyId, customerId=$customerId, customerName=$customerName, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateCompanyBenefitsResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateCompanyBenefitsResponse.kt index 5e4f0d487..b0620064e 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateCompanyBenefitsResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/CreateCompanyBenefitsResponse.kt @@ -162,6 +162,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): CreateCompanyBenefitsResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryCreateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryCreateResponse.kt index f5c0cf3c9..1eb23ce77 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryCreateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryCreateResponse.kt @@ -75,6 +75,14 @@ private constructor(private val additionalProperties: MutableMap, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -36,17 +37,19 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -75,6 +78,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -116,6 +127,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -162,6 +180,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -171,6 +190,7 @@ private constructor( accountId = directoryEvent.accountId companyId = directoryEvent.companyId connectionId = directoryEvent.connectionId + entityId = directoryEvent.entityId data = directoryEvent.data eventType = directoryEvent.eventType additionalProperties = directoryEvent.additionalProperties.toMutableMap() @@ -224,6 +244,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: Data) = data(JsonField.of(data)) /** @@ -282,6 +313,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -290,6 +322,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): DirectoryEvent = apply { if (validated) { return@apply @@ -298,6 +338,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -321,6 +362,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -429,6 +471,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -567,6 +618,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -614,17 +674,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "DirectoryEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "DirectoryEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryListIndividualsResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryListIndividualsResponse.kt index 123a2cb5f..806d599f1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryListIndividualsResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DirectoryListIndividualsResponse.kt @@ -187,6 +187,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): DirectoryListIndividualsResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DisconnectResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DisconnectResponse.kt index 4115c896e..06391e0f8 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DisconnectResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DisconnectResponse.kt @@ -127,6 +127,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): DisconnectResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentListResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentListResponse.kt index a4d67b183..13bcb80ac 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentListResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentListResponse.kt @@ -179,6 +179,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): DocumentListResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentResponse.kt index 7e7025608..a84246dc0 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentResponse.kt @@ -283,6 +283,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): DocumentResponse = apply { if (validated) { return@apply @@ -404,6 +412,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentRetreiveResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentRetreiveResponse.kt index 59bee092a..1834a1d1d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentRetreiveResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/DocumentRetreiveResponse.kt @@ -61,6 +61,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = documentRetreiveResponse.accept(new DocumentRetreiveResponse.Visitor>() { + * @Override + * public Optional visitW42020(W42020 w42020) { + * return Optional.of(w42020.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and the + * current variant is unknown. + */ fun accept(visitor: Visitor): T = when { w42020 != null -> visitor.visitW42020(w42020) @@ -70,6 +99,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): DocumentRetreiveResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentData.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentData.kt index 2156ba87d..0e62683fe 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentData.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentData.kt @@ -35,34 +35,71 @@ import kotlin.jvm.optionals.getOrNull @JsonSerialize(using = EmploymentData.Serializer::class) class EmploymentData private constructor( - private val unionMember0: UnionMember0? = null, + private val employmentData: InnerEmploymentData? = null, private val batchError: BatchError? = null, private val _json: JsonValue? = null, ) { - fun unionMember0(): Optional = Optional.ofNullable(unionMember0) + fun employmentData(): Optional = Optional.ofNullable(employmentData) fun batchError(): Optional = Optional.ofNullable(batchError) - fun isUnionMember0(): Boolean = unionMember0 != null + fun isEmploymentData(): Boolean = employmentData != null fun isBatchError(): Boolean = batchError != null - fun asUnionMember0(): UnionMember0 = unionMember0.getOrThrow("unionMember0") + fun asEmploymentData(): InnerEmploymentData = employmentData.getOrThrow("employmentData") fun asBatchError(): BatchError = batchError.getOrThrow("batchError") fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = employmentData.accept(new EmploymentData.Visitor>() { + * @Override + * public Optional visitEmploymentData(InnerEmploymentData employmentData) { + * return Optional.of(employmentData.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and the + * current variant is unknown. + */ fun accept(visitor: Visitor): T = when { - unionMember0 != null -> visitor.visitUnionMember0(unionMember0) + employmentData != null -> visitor.visitEmploymentData(employmentData) batchError != null -> visitor.visitBatchError(batchError) else -> visitor.unknown(_json) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): EmploymentData = apply { if (validated) { return@apply @@ -70,8 +107,8 @@ private constructor( accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) { - unionMember0.validate() + override fun visitEmploymentData(employmentData: InnerEmploymentData) { + employmentData.validate() } override fun visitBatchError(batchError: BatchError) { @@ -99,7 +136,8 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) = unionMember0.validity() + override fun visitEmploymentData(employmentData: InnerEmploymentData) = + employmentData.validity() override fun visitBatchError(batchError: BatchError) = batchError.validity() @@ -113,15 +151,15 @@ private constructor( } return other is EmploymentData && - unionMember0 == other.unionMember0 && + employmentData == other.employmentData && batchError == other.batchError } - override fun hashCode(): Int = Objects.hash(unionMember0, batchError) + override fun hashCode(): Int = Objects.hash(employmentData, batchError) override fun toString(): String = when { - unionMember0 != null -> "EmploymentData{unionMember0=$unionMember0}" + employmentData != null -> "EmploymentData{employmentData=$employmentData}" batchError != null -> "EmploymentData{batchError=$batchError}" _json != null -> "EmploymentData{_unknown=$_json}" else -> throw IllegalStateException("Invalid EmploymentData") @@ -130,7 +168,8 @@ private constructor( companion object { @JvmStatic - fun ofUnionMember0(unionMember0: UnionMember0) = EmploymentData(unionMember0 = unionMember0) + fun ofEmploymentData(employmentData: InnerEmploymentData) = + EmploymentData(employmentData = employmentData) @JvmStatic fun ofBatchError(batchError: BatchError) = EmploymentData(batchError = batchError) @@ -141,7 +180,7 @@ private constructor( */ interface Visitor { - fun visitUnionMember0(unionMember0: UnionMember0): T + fun visitEmploymentData(employmentData: InnerEmploymentData): T fun visitBatchError(batchError: BatchError): T @@ -167,8 +206,8 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - EmploymentData(unionMember0 = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + EmploymentData(employmentData = it, _json = json) }, tryDeserialize(node, jacksonTypeRef())?.let { EmploymentData(batchError = it, _json = json) @@ -197,7 +236,7 @@ private constructor( provider: SerializerProvider, ) { when { - value.unionMember0 != null -> generator.writeObject(value.unionMember0) + value.employmentData != null -> generator.writeObject(value.employmentData) value.batchError != null -> generator.writeObject(value.batchError) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid EmploymentData") @@ -205,7 +244,7 @@ private constructor( } } - class UnionMember0 + class InnerEmploymentData @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val id: JsonField, @@ -215,6 +254,7 @@ private constructor( private val employmentStatus: JsonField, private val endDate: JsonField, private val firstName: JsonField, + private val flsaStatus: JsonField, private val isActive: JsonField, private val lastName: JsonField, private val latestRehireDate: JsonField, @@ -250,6 +290,9 @@ private constructor( @JsonProperty("first_name") @ExcludeMissing firstName: JsonField = JsonMissing.of(), + @JsonProperty("flsa_status") + @ExcludeMissing + flsaStatus: JsonField = JsonMissing.of(), @JsonProperty("is_active") @ExcludeMissing isActive: JsonField = JsonMissing.of(), @@ -289,6 +332,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, isActive, lastName, latestRehireDate, @@ -360,6 +404,14 @@ private constructor( */ fun firstName(): Optional = firstName.getOptional("first_name") + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun flsaStatus(): Optional = flsaStatus.getOptional("flsa_status") + /** * `true` if the individual an an active employee or contractor at the company. * @@ -518,6 +570,15 @@ private constructor( */ @JsonProperty("first_name") @ExcludeMissing fun _firstName(): JsonField = firstName + /** + * Returns the raw JSON value of [flsaStatus]. + * + * Unlike [flsaStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("flsa_status") + @ExcludeMissing + fun _flsaStatus(): JsonField = flsaStatus + /** * Returns the raw JSON value of [isActive]. * @@ -638,7 +699,7 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember0]. + * Returns a mutable builder for constructing an instance of [InnerEmploymentData]. * * The following fields are required: * ```java @@ -649,6 +710,7 @@ private constructor( * .employmentStatus() * .endDate() * .firstName() + * .flsaStatus() * .isActive() * .lastName() * .latestRehireDate() @@ -662,7 +724,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember0]. */ + /** A builder for [InnerEmploymentData]. */ class Builder internal constructor() { private var id: JsonField? = null @@ -672,6 +734,7 @@ private constructor( private var employmentStatus: JsonField? = null private var endDate: JsonField? = null private var firstName: JsonField? = null + private var flsaStatus: JsonField? = null private var isActive: JsonField? = null private var lastName: JsonField? = null private var latestRehireDate: JsonField? = null @@ -688,28 +751,29 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(unionMember0: UnionMember0) = apply { - id = unionMember0.id - classCode = unionMember0.classCode - department = unionMember0.department - employment = unionMember0.employment - employmentStatus = unionMember0.employmentStatus - endDate = unionMember0.endDate - firstName = unionMember0.firstName - isActive = unionMember0.isActive - lastName = unionMember0.lastName - latestRehireDate = unionMember0.latestRehireDate - location = unionMember0.location - manager = unionMember0.manager - middleName = unionMember0.middleName - startDate = unionMember0.startDate - title = unionMember0.title - customFields = unionMember0.customFields.map { it.toMutableList() } - income = unionMember0.income - incomeHistory = unionMember0.incomeHistory.map { it.toMutableList() } - sourceId = unionMember0.sourceId - workId = unionMember0.workId - additionalProperties = unionMember0.additionalProperties.toMutableMap() + internal fun from(innerEmploymentData: InnerEmploymentData) = apply { + id = innerEmploymentData.id + classCode = innerEmploymentData.classCode + department = innerEmploymentData.department + employment = innerEmploymentData.employment + employmentStatus = innerEmploymentData.employmentStatus + endDate = innerEmploymentData.endDate + firstName = innerEmploymentData.firstName + flsaStatus = innerEmploymentData.flsaStatus + isActive = innerEmploymentData.isActive + lastName = innerEmploymentData.lastName + latestRehireDate = innerEmploymentData.latestRehireDate + location = innerEmploymentData.location + manager = innerEmploymentData.manager + middleName = innerEmploymentData.middleName + startDate = innerEmploymentData.startDate + title = innerEmploymentData.title + customFields = innerEmploymentData.customFields.map { it.toMutableList() } + income = innerEmploymentData.income + incomeHistory = innerEmploymentData.incomeHistory.map { it.toMutableList() } + sourceId = innerEmploymentData.sourceId + workId = innerEmploymentData.workId + additionalProperties = innerEmploymentData.additionalProperties.toMutableMap() } /** A stable Finch `id` (UUID v4) for an individual in the company. */ @@ -823,6 +887,26 @@ private constructor( */ fun firstName(firstName: JsonField) = apply { this.firstName = firstName } + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, + * `unknown`. + */ + fun flsaStatus(flsaStatus: FlsaStatus?) = flsaStatus(JsonField.ofNullable(flsaStatus)) + + /** Alias for calling [Builder.flsaStatus] with `flsaStatus.orElse(null)`. */ + fun flsaStatus(flsaStatus: Optional) = flsaStatus(flsaStatus.getOrNull()) + + /** + * Sets [Builder.flsaStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.flsaStatus] with a well-typed [FlsaStatus] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun flsaStatus(flsaStatus: JsonField) = apply { + this.flsaStatus = flsaStatus + } + /** `true` if the individual an an active employee or contractor at the company. */ fun isActive(isActive: Boolean?) = isActive(JsonField.ofNullable(isActive)) @@ -1090,7 +1174,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember0]. + * Returns an immutable instance of [InnerEmploymentData]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -1103,6 +1187,7 @@ private constructor( * .employmentStatus() * .endDate() * .firstName() + * .flsaStatus() * .isActive() * .lastName() * .latestRehireDate() @@ -1115,8 +1200,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember0 = - UnionMember0( + fun build(): InnerEmploymentData = + InnerEmploymentData( checkRequired("id", id), checkRequired("classCode", classCode), checkRequired("department", department), @@ -1124,6 +1209,7 @@ private constructor( checkRequired("employmentStatus", employmentStatus), checkRequired("endDate", endDate), checkRequired("firstName", firstName), + checkRequired("flsaStatus", flsaStatus), checkRequired("isActive", isActive), checkRequired("lastName", lastName), checkRequired("latestRehireDate", latestRehireDate), @@ -1143,7 +1229,16 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember0 = apply { + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InnerEmploymentData = apply { if (validated) { return@apply } @@ -1155,6 +1250,7 @@ private constructor( employmentStatus().ifPresent { it.validate() } endDate() firstName() + flsaStatus().ifPresent { it.validate() } isActive() lastName() latestRehireDate() @@ -1194,6 +1290,7 @@ private constructor( (employmentStatus.asKnown().getOrNull()?.validity() ?: 0) + (if (endDate.asKnown().isPresent) 1 else 0) + (if (firstName.asKnown().isPresent) 1 else 0) + + (flsaStatus.asKnown().getOrNull()?.validity() ?: 0) + (if (isActive.asKnown().isPresent) 1 else 0) + (if (lastName.asKnown().isPresent) 1 else 0) + (if (latestRehireDate.asKnown().isPresent) 1 else 0) + @@ -1329,6 +1426,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -1538,6 +1645,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Employment = apply { if (validated) { return@apply @@ -1688,6 +1805,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Subtype = apply { if (validated) { return@apply @@ -1819,6 +1946,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2002,6 +2139,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmploymentStatus = apply { if (validated) { return@apply @@ -2040,6 +2187,156 @@ private constructor( override fun toString() = value.toString() } + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + */ + class FlsaStatus @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val EXEMPT = of("exempt") + + @JvmField val NON_EXEMPT = of("non_exempt") + + @JvmField val UNKNOWN = of("unknown") + + @JvmStatic fun of(value: String) = FlsaStatus(JsonField.of(value)) + } + + /** An enum containing [FlsaStatus]'s known values. */ + enum class Known { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + } + + /** + * An enum containing [FlsaStatus]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [FlsaStatus] 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 { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + /** + * An enum member indicating that [FlsaStatus] 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) { + EXEMPT -> Value.EXEMPT + NON_EXEMPT -> Value.NON_EXEMPT + UNKNOWN -> Value.UNKNOWN + 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 FinchInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + EXEMPT -> Known.EXEMPT + NON_EXEMPT -> Known.NON_EXEMPT + UNKNOWN -> Known.UNKNOWN + else -> throw FinchInvalidDataException("Unknown FlsaStatus: $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 FinchInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + FinchInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): FlsaStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: FinchInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FlsaStatus && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + /** The manager object representing the manager of the individual within the org. */ class Manager @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -2158,6 +2455,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Manager = apply { if (validated) { return@apply @@ -2349,6 +2656,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CustomField = apply { if (validated) { return@apply @@ -2422,6 +2739,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = value.accept(new Value.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -2434,6 +2781,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Value = apply { if (validated) { return@apply @@ -2643,7 +3000,7 @@ private constructor( return true } - return other is UnionMember0 && + return other is InnerEmploymentData && id == other.id && classCode == other.classCode && department == other.department && @@ -2651,6 +3008,7 @@ private constructor( employmentStatus == other.employmentStatus && endDate == other.endDate && firstName == other.firstName && + flsaStatus == other.flsaStatus && isActive == other.isActive && lastName == other.lastName && latestRehireDate == other.latestRehireDate && @@ -2676,6 +3034,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, isActive, lastName, latestRehireDate, @@ -2696,7 +3055,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember0{id=$id, classCode=$classCode, department=$department, employment=$employment, employmentStatus=$employmentStatus, endDate=$endDate, firstName=$firstName, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, startDate=$startDate, title=$title, customFields=$customFields, income=$income, incomeHistory=$incomeHistory, sourceId=$sourceId, workId=$workId, additionalProperties=$additionalProperties}" + "InnerEmploymentData{id=$id, classCode=$classCode, department=$department, employment=$employment, employmentStatus=$employmentStatus, endDate=$endDate, firstName=$firstName, flsaStatus=$flsaStatus, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, startDate=$startDate, title=$title, customFields=$customFields, income=$income, incomeHistory=$incomeHistory, sourceId=$sourceId, workId=$workId, additionalProperties=$additionalProperties}" } class BatchError @@ -2905,6 +3264,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BatchError = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentDataResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentDataResponse.kt index 1c1250448..d308bf8bc 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentDataResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentDataResponse.kt @@ -131,9 +131,9 @@ private constructor( */ fun body(body: JsonField) = apply { this.body = body } - /** Alias for calling [body] with `EmploymentData.ofUnionMember0(unionMember0)`. */ - fun body(unionMember0: EmploymentData.UnionMember0) = - body(EmploymentData.ofUnionMember0(unionMember0)) + /** Alias for calling [body] with `EmploymentData.ofEmploymentData(employmentData)`. */ + fun body(employmentData: EmploymentData.InnerEmploymentData) = + body(EmploymentData.ofEmploymentData(employmentData)) /** Alias for calling [body] with `EmploymentData.ofBatchError(batchError)`. */ fun body(batchError: EmploymentData.BatchError) = @@ -207,6 +207,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): EmploymentDataResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentEvent.kt index b09dd927a..aef62c9c5 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentEvent.kt @@ -24,6 +24,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -36,17 +37,19 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -75,6 +78,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -116,6 +127,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -162,6 +180,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -171,6 +190,7 @@ private constructor( accountId = employmentEvent.accountId companyId = employmentEvent.companyId connectionId = employmentEvent.connectionId + entityId = employmentEvent.entityId data = employmentEvent.data eventType = employmentEvent.eventType additionalProperties = employmentEvent.additionalProperties.toMutableMap() @@ -224,6 +244,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: Data) = data(JsonField.of(data)) /** @@ -282,6 +313,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -290,6 +322,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): EmploymentEvent = apply { if (validated) { return@apply @@ -298,6 +338,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -321,6 +362,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -429,6 +471,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -567,6 +618,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -614,17 +674,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "EmploymentEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "EmploymentEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentUpdateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentUpdateResponse.kt index c4aaf053a..3cfab65ac 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentUpdateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EmploymentUpdateResponse.kt @@ -30,6 +30,7 @@ private constructor( private val employmentStatus: JsonField, private val endDate: JsonField, private val firstName: JsonField, + private val flsaStatus: JsonField, private val income: JsonField, private val incomeHistory: JsonField>, private val isActive: JsonField, @@ -62,6 +63,9 @@ private constructor( employmentStatus: JsonField = JsonMissing.of(), @JsonProperty("end_date") @ExcludeMissing endDate: JsonField = JsonMissing.of(), @JsonProperty("first_name") @ExcludeMissing firstName: JsonField = JsonMissing.of(), + @JsonProperty("flsa_status") + @ExcludeMissing + flsaStatus: JsonField = JsonMissing.of(), @JsonProperty("income") @ExcludeMissing income: JsonField = JsonMissing.of(), @JsonProperty("income_history") @ExcludeMissing @@ -88,6 +92,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, income, incomeHistory, isActive, @@ -166,6 +171,14 @@ private constructor( */ fun firstName(): Optional = firstName.getOptional("first_name") + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun flsaStatus(): Optional = flsaStatus.getOptional("flsa_status") + /** * The employee's income as reported by the provider. This may not always be annualized income, * but may be in units of bi-weekly, semi-monthly, daily, etc, depending on what information the @@ -315,6 +328,15 @@ private constructor( */ @JsonProperty("first_name") @ExcludeMissing fun _firstName(): JsonField = firstName + /** + * Returns the raw JSON value of [flsaStatus]. + * + * Unlike [flsaStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("flsa_status") + @ExcludeMissing + fun _flsaStatus(): JsonField = flsaStatus + /** * Returns the raw JSON value of [income]. * @@ -426,6 +448,7 @@ private constructor( private var employmentStatus: JsonField = JsonMissing.of() private var endDate: JsonField = JsonMissing.of() private var firstName: JsonField = JsonMissing.of() + private var flsaStatus: JsonField = JsonMissing.of() private var income: JsonField = JsonMissing.of() private var incomeHistory: JsonField>? = null private var isActive: JsonField = JsonMissing.of() @@ -449,6 +472,7 @@ private constructor( employmentStatus = employmentUpdateResponse.employmentStatus endDate = employmentUpdateResponse.endDate firstName = employmentUpdateResponse.firstName + flsaStatus = employmentUpdateResponse.flsaStatus income = employmentUpdateResponse.income incomeHistory = employmentUpdateResponse.incomeHistory.map { it.toMutableList() } isActive = employmentUpdateResponse.isActive @@ -600,6 +624,23 @@ private constructor( */ fun firstName(firstName: JsonField) = apply { this.firstName = firstName } + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + */ + fun flsaStatus(flsaStatus: FlsaStatus?) = flsaStatus(JsonField.ofNullable(flsaStatus)) + + /** Alias for calling [Builder.flsaStatus] with `flsaStatus.orElse(null)`. */ + fun flsaStatus(flsaStatus: Optional) = flsaStatus(flsaStatus.getOrNull()) + + /** + * Sets [Builder.flsaStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.flsaStatus] with a well-typed [FlsaStatus] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun flsaStatus(flsaStatus: JsonField) = apply { this.flsaStatus = flsaStatus } + /** * The employee's income as reported by the provider. This may not always be annualized * income, but may be in units of bi-weekly, semi-monthly, daily, etc, depending on what @@ -822,6 +863,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, income, (incomeHistory ?: JsonMissing.of()).map { it.toImmutable() }, isActive, @@ -839,6 +881,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): EmploymentUpdateResponse = apply { if (validated) { return@apply @@ -852,6 +902,7 @@ private constructor( employmentStatus().ifPresent { it.validate() } endDate() firstName() + flsaStatus().ifPresent { it.validate() } income().ifPresent { it.validate() } incomeHistory().ifPresent { it.forEach { it?.validate() } } isActive() @@ -889,6 +940,7 @@ private constructor( (employmentStatus.asKnown().getOrNull()?.validity() ?: 0) + (if (endDate.asKnown().isPresent) 1 else 0) + (if (firstName.asKnown().isPresent) 1 else 0) + + (flsaStatus.asKnown().getOrNull()?.validity() ?: 0) + (income.asKnown().getOrNull()?.validity() ?: 0) + (incomeHistory.asKnown().getOrNull()?.sumOf { (it?.validity() ?: 0).toInt() } ?: 0) + (if (isActive.asKnown().isPresent) 1 else 0) + @@ -1013,6 +1065,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CustomField = apply { if (validated) { return@apply @@ -1159,6 +1220,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -1342,6 +1412,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Employment = apply { if (validated) { return@apply @@ -1491,6 +1570,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Subtype = apply { if (validated) { return@apply @@ -1619,6 +1708,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1797,6 +1896,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmploymentStatus = apply { if (validated) { return@apply @@ -1835,6 +1943,148 @@ private constructor( override fun toString() = value.toString() } + /** The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. */ + class FlsaStatus @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val EXEMPT = of("exempt") + + @JvmField val NON_EXEMPT = of("non_exempt") + + @JvmField val UNKNOWN = of("unknown") + + @JvmStatic fun of(value: String) = FlsaStatus(JsonField.of(value)) + } + + /** An enum containing [FlsaStatus]'s known values. */ + enum class Known { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + } + + /** + * An enum containing [FlsaStatus]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [FlsaStatus] 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 { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + /** + * An enum member indicating that [FlsaStatus] 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) { + EXEMPT -> Value.EXEMPT + NON_EXEMPT -> Value.NON_EXEMPT + UNKNOWN -> Value.UNKNOWN + 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 FinchInvalidDataException if this class instance's value is a not a known member. + */ + fun known(): Known = + when (this) { + EXEMPT -> Known.EXEMPT + NON_EXEMPT -> Known.NON_EXEMPT + UNKNOWN -> Known.UNKNOWN + else -> throw FinchInvalidDataException("Unknown FlsaStatus: $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 FinchInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { FinchInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): FlsaStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: FinchInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FlsaStatus && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + /** The manager object representing the manager of the individual within the org. */ class Manager @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -1934,6 +2184,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Manager = apply { if (validated) { return@apply @@ -1990,6 +2249,7 @@ private constructor( employmentStatus == other.employmentStatus && endDate == other.endDate && firstName == other.firstName && + flsaStatus == other.flsaStatus && income == other.income && incomeHistory == other.incomeHistory && isActive == other.isActive && @@ -2014,6 +2274,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, income, incomeHistory, isActive, @@ -2032,5 +2293,5 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "EmploymentUpdateResponse{id=$id, classCode=$classCode, customFields=$customFields, department=$department, employment=$employment, employmentStatus=$employmentStatus, endDate=$endDate, firstName=$firstName, income=$income, incomeHistory=$incomeHistory, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, sourceId=$sourceId, startDate=$startDate, title=$title, additionalProperties=$additionalProperties}" + "EmploymentUpdateResponse{id=$id, classCode=$classCode, customFields=$customFields, department=$department, employment=$employment, employmentStatus=$employmentStatus, endDate=$endDate, firstName=$firstName, flsaStatus=$flsaStatus, income=$income, incomeHistory=$incomeHistory, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, sourceId=$sourceId, startDate=$startDate, title=$title, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EnrolledIndividualBenefitResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EnrolledIndividualBenefitResponse.kt index 145930fbc..8dac5e874 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EnrolledIndividualBenefitResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/EnrolledIndividualBenefitResponse.kt @@ -130,6 +130,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): EnrolledIndividualBenefitResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitCreateParams.kt index d5242dbe9..d5174fdcc 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitCreateParams.kt @@ -615,6 +615,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -833,6 +842,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BenefitCompanyMatchContribution = apply { if (validated) { return@apply @@ -1014,6 +1032,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tier = apply { if (validated) { return@apply @@ -1147,6 +1175,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitIndividualUnenrollManyParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitIndividualUnenrollManyParams.kt index 5d3a72896..84930e4fe 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitIndividualUnenrollManyParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitIndividualUnenrollManyParams.kt @@ -418,6 +418,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitUpdateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitUpdateParams.kt index 1465b2080..3387c8f0f 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitUpdateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisBenefitUpdateParams.kt @@ -383,6 +383,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListPageResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListPageResponse.kt index 733495055..bcc140651 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListPageResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListPageResponse.kt @@ -155,6 +155,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): HrisCompanyPayStatementItemListPageResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListParams.kt index e6fa3de65..27380a67d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemListParams.kt @@ -397,6 +397,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Category = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleCreateParams.kt index 85822d80e..3d6dc31a1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleCreateParams.kt @@ -709,6 +709,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CreateRuleRequest = apply { if (validated) { return@apply @@ -880,6 +889,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -971,6 +989,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -1193,6 +1221,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Condition = apply { if (validated) { return@apply @@ -1311,6 +1348,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply @@ -1454,6 +1501,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EntityType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleListPageResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleListPageResponse.kt index 0c2ad0959..f80d78965 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleListPageResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleListPageResponse.kt @@ -155,6 +155,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): HrisCompanyPayStatementItemRuleListPageResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleUpdateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleUpdateParams.kt index e7e0f2f00..b75a20e03 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleUpdateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisCompanyPayStatementItemRuleUpdateParams.kt @@ -358,6 +358,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): UpdateRuleRequest = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDirectoryListPageResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDirectoryListPageResponse.kt index 6371534cf..2bc878018 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDirectoryListPageResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDirectoryListPageResponse.kt @@ -184,6 +184,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): HrisDirectoryListPageResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDocumentListParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDocumentListParams.kt index 3aa700a15..52ecf5923 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDocumentListParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisDocumentListParams.kt @@ -374,6 +374,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponse.kt index 60b698203..2265abc76 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponse.kt @@ -153,6 +153,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): HrisEmploymentRetrieveManyPageResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyParams.kt index 98ac3888c..7e4b722ca 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyParams.kt @@ -421,6 +421,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -595,6 +604,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Request = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponse.kt index 19a231b82..7fd8bedee 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponse.kt @@ -153,6 +153,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): HrisIndividualRetrieveManyPageResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyParams.kt index b9026b965..9f6ee8686 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyParams.kt @@ -448,6 +448,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -611,6 +620,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Options = apply { if (validated) { return@apply @@ -756,6 +774,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Request = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyPageResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyPageResponse.kt index 2825d3469..14bf592eb 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyPageResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyPageResponse.kt @@ -154,6 +154,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): HrisPayStatementRetrieveManyPageResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyParams.kt index 76e7daeed..56e6629a1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/HrisPayStatementRetrieveManyParams.kt @@ -424,6 +424,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -651,6 +660,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Request = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Income.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Income.kt index 0e9abdc2d..887ff22c8 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Income.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Income.kt @@ -270,6 +270,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Income = apply { if (validated) { return@apply @@ -434,6 +442,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Unit = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Individual.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Individual.kt index c9ee65cf5..122fb0fd2 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Individual.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Individual.kt @@ -35,34 +35,71 @@ import kotlin.jvm.optionals.getOrNull @JsonSerialize(using = Individual.Serializer::class) class Individual private constructor( - private val unionMember0: UnionMember0? = null, + private val individual: InnerIndividual? = null, private val batchError: BatchError? = null, private val _json: JsonValue? = null, ) { - fun unionMember0(): Optional = Optional.ofNullable(unionMember0) + fun individual(): Optional = Optional.ofNullable(individual) fun batchError(): Optional = Optional.ofNullable(batchError) - fun isUnionMember0(): Boolean = unionMember0 != null + fun isIndividual(): Boolean = individual != null fun isBatchError(): Boolean = batchError != null - fun asUnionMember0(): UnionMember0 = unionMember0.getOrThrow("unionMember0") + fun asIndividual(): InnerIndividual = individual.getOrThrow("individual") fun asBatchError(): BatchError = batchError.getOrThrow("batchError") fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = individual.accept(new Individual.Visitor>() { + * @Override + * public Optional visitIndividual(InnerIndividual individual) { + * return Optional.of(individual.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and the + * current variant is unknown. + */ fun accept(visitor: Visitor): T = when { - unionMember0 != null -> visitor.visitUnionMember0(unionMember0) + individual != null -> visitor.visitIndividual(individual) batchError != null -> visitor.visitBatchError(batchError) else -> visitor.unknown(_json) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Individual = apply { if (validated) { return@apply @@ -70,8 +107,8 @@ private constructor( accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) { - unionMember0.validate() + override fun visitIndividual(individual: InnerIndividual) { + individual.validate() } override fun visitBatchError(batchError: BatchError) { @@ -99,7 +136,7 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) = unionMember0.validity() + override fun visitIndividual(individual: InnerIndividual) = individual.validity() override fun visitBatchError(batchError: BatchError) = batchError.validity() @@ -113,15 +150,15 @@ private constructor( } return other is Individual && - unionMember0 == other.unionMember0 && + individual == other.individual && batchError == other.batchError } - override fun hashCode(): Int = Objects.hash(unionMember0, batchError) + override fun hashCode(): Int = Objects.hash(individual, batchError) override fun toString(): String = when { - unionMember0 != null -> "Individual{unionMember0=$unionMember0}" + individual != null -> "Individual{individual=$individual}" batchError != null -> "Individual{batchError=$batchError}" _json != null -> "Individual{_unknown=$_json}" else -> throw IllegalStateException("Invalid Individual") @@ -130,7 +167,7 @@ private constructor( companion object { @JvmStatic - fun ofUnionMember0(unionMember0: UnionMember0) = Individual(unionMember0 = unionMember0) + fun ofIndividual(individual: InnerIndividual) = Individual(individual = individual) @JvmStatic fun ofBatchError(batchError: BatchError) = Individual(batchError = batchError) } @@ -138,7 +175,7 @@ private constructor( /** An interface that defines how to map each variant of [Individual] to a value of type [T]. */ interface Visitor { - fun visitUnionMember0(unionMember0: UnionMember0): T + fun visitIndividual(individual: InnerIndividual): T fun visitBatchError(batchError: BatchError): T @@ -163,8 +200,8 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Individual(unionMember0 = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + Individual(individual = it, _json = json) }, tryDeserialize(node, jacksonTypeRef())?.let { Individual(batchError = it, _json = json) @@ -193,7 +230,7 @@ private constructor( provider: SerializerProvider, ) { when { - value.unionMember0 != null -> generator.writeObject(value.unionMember0) + value.individual != null -> generator.writeObject(value.individual) value.batchError != null -> generator.writeObject(value.batchError) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Individual") @@ -201,7 +238,7 @@ private constructor( } } - class UnionMember0 + class InnerIndividual @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val id: JsonField, @@ -489,7 +526,7 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember0]. + * Returns a mutable builder for constructing an instance of [InnerIndividual]. * * The following fields are required: * ```java @@ -508,7 +545,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember0]. */ + /** A builder for [InnerIndividual]. */ class Builder internal constructor() { private var id: JsonField? = null @@ -527,21 +564,21 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(unionMember0: UnionMember0) = apply { - id = unionMember0.id - dob = unionMember0.dob - ethnicity = unionMember0.ethnicity - firstName = unionMember0.firstName - gender = unionMember0.gender - lastName = unionMember0.lastName - middleName = unionMember0.middleName - phoneNumbers = unionMember0.phoneNumbers.map { it.toMutableList() } - preferredName = unionMember0.preferredName - residence = unionMember0.residence - emails = unionMember0.emails.map { it.toMutableList() } - encryptedSsn = unionMember0.encryptedSsn - ssn = unionMember0.ssn - additionalProperties = unionMember0.additionalProperties.toMutableMap() + internal fun from(innerIndividual: InnerIndividual) = apply { + id = innerIndividual.id + dob = innerIndividual.dob + ethnicity = innerIndividual.ethnicity + firstName = innerIndividual.firstName + gender = innerIndividual.gender + lastName = innerIndividual.lastName + middleName = innerIndividual.middleName + phoneNumbers = innerIndividual.phoneNumbers.map { it.toMutableList() } + preferredName = innerIndividual.preferredName + residence = innerIndividual.residence + emails = innerIndividual.emails.map { it.toMutableList() } + encryptedSsn = innerIndividual.encryptedSsn + ssn = innerIndividual.ssn + additionalProperties = innerIndividual.additionalProperties.toMutableMap() } /** A stable Finch `id` (UUID v4) for an individual in the company. */ @@ -798,7 +835,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember0]. + * Returns an immutable instance of [InnerIndividual]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -818,8 +855,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember0 = - UnionMember0( + fun build(): InnerIndividual = + InnerIndividual( checkRequired("id", id), checkRequired("dob", dob), checkRequired("ethnicity", ethnicity), @@ -839,7 +876,16 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember0 = apply { + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InnerIndividual = apply { if (validated) { return@apply } @@ -1022,6 +1068,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Ethnicity = apply { if (validated) { return@apply @@ -1164,6 +1220,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Gender = apply { if (validated) { return@apply @@ -1355,6 +1421,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PhoneNumber = apply { if (validated) { return@apply @@ -1476,6 +1552,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1684,6 +1770,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Email = apply { if (validated) { return@apply @@ -1805,6 +1901,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1867,7 +1973,7 @@ private constructor( return true } - return other is UnionMember0 && + return other is InnerIndividual && id == other.id && dob == other.dob && ethnicity == other.ethnicity && @@ -1906,7 +2012,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember0{id=$id, dob=$dob, ethnicity=$ethnicity, firstName=$firstName, gender=$gender, lastName=$lastName, middleName=$middleName, phoneNumbers=$phoneNumbers, preferredName=$preferredName, residence=$residence, emails=$emails, encryptedSsn=$encryptedSsn, ssn=$ssn, additionalProperties=$additionalProperties}" + "InnerIndividual{id=$id, dob=$dob, ethnicity=$ethnicity, firstName=$firstName, gender=$gender, lastName=$lastName, middleName=$middleName, phoneNumbers=$phoneNumbers, preferredName=$preferredName, residence=$residence, emails=$emails, encryptedSsn=$encryptedSsn, ssn=$ssn, additionalProperties=$additionalProperties}" } class BatchError @@ -2115,6 +2221,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BatchError = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualBenefit.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualBenefit.kt index 4e5c86ced..5c4976137 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualBenefit.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualBenefit.kt @@ -143,8 +143,9 @@ private constructor( */ fun body(body: JsonField) = apply { this.body = body } - /** Alias for calling [body] with `Body.ofUnionMember0(unionMember0)`. */ - fun body(unionMember0: Body.UnionMember0) = body(Body.ofUnionMember0(unionMember0)) + /** Alias for calling [body] with `Body.ofIndividualBenefit(individualBenefit)`. */ + fun body(individualBenefit: Body.InnerIndividualBenefit) = + body(Body.ofIndividualBenefit(individualBenefit)) /** Alias for calling [body] with `Body.ofBatchError(batchError)`. */ fun body(batchError: Body.BatchError) = body(Body.ofBatchError(batchError)) @@ -216,6 +217,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): IndividualBenefit = apply { if (validated) { return@apply @@ -250,34 +259,74 @@ private constructor( @JsonSerialize(using = Body.Serializer::class) class Body private constructor( - private val unionMember0: UnionMember0? = null, + private val individualBenefit: InnerIndividualBenefit? = null, private val batchError: BatchError? = null, private val _json: JsonValue? = null, ) { - fun unionMember0(): Optional = Optional.ofNullable(unionMember0) + fun individualBenefit(): Optional = + Optional.ofNullable(individualBenefit) fun batchError(): Optional = Optional.ofNullable(batchError) - fun isUnionMember0(): Boolean = unionMember0 != null + fun isIndividualBenefit(): Boolean = individualBenefit != null fun isBatchError(): Boolean = batchError != null - fun asUnionMember0(): UnionMember0 = unionMember0.getOrThrow("unionMember0") + fun asIndividualBenefit(): InnerIndividualBenefit = + individualBenefit.getOrThrow("individualBenefit") fun asBatchError(): BatchError = batchError.getOrThrow("batchError") fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = body.accept(new Body.Visitor>() { + * @Override + * public Optional visitIndividualBenefit(InnerIndividualBenefit individualBenefit) { + * return Optional.of(individualBenefit.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { - unionMember0 != null -> visitor.visitUnionMember0(unionMember0) + individualBenefit != null -> visitor.visitIndividualBenefit(individualBenefit) batchError != null -> visitor.visitBatchError(batchError) else -> visitor.unknown(_json) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -285,8 +334,8 @@ private constructor( accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) { - unionMember0.validate() + override fun visitIndividualBenefit(individualBenefit: InnerIndividualBenefit) { + individualBenefit.validate() } override fun visitBatchError(batchError: BatchError) { @@ -315,8 +364,8 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitUnionMember0(unionMember0: UnionMember0) = - unionMember0.validity() + override fun visitIndividualBenefit(individualBenefit: InnerIndividualBenefit) = + individualBenefit.validity() override fun visitBatchError(batchError: BatchError) = batchError.validity() @@ -330,15 +379,15 @@ private constructor( } return other is Body && - unionMember0 == other.unionMember0 && + individualBenefit == other.individualBenefit && batchError == other.batchError } - override fun hashCode(): Int = Objects.hash(unionMember0, batchError) + override fun hashCode(): Int = Objects.hash(individualBenefit, batchError) override fun toString(): String = when { - unionMember0 != null -> "Body{unionMember0=$unionMember0}" + individualBenefit != null -> "Body{individualBenefit=$individualBenefit}" batchError != null -> "Body{batchError=$batchError}" _json != null -> "Body{_unknown=$_json}" else -> throw IllegalStateException("Invalid Body") @@ -347,7 +396,8 @@ private constructor( companion object { @JvmStatic - fun ofUnionMember0(unionMember0: UnionMember0) = Body(unionMember0 = unionMember0) + fun ofIndividualBenefit(individualBenefit: InnerIndividualBenefit) = + Body(individualBenefit = individualBenefit) @JvmStatic fun ofBatchError(batchError: BatchError) = Body(batchError = batchError) } @@ -355,7 +405,7 @@ private constructor( /** An interface that defines how to map each variant of [Body] to a value of type [T]. */ interface Visitor { - fun visitUnionMember0(unionMember0: UnionMember0): T + fun visitIndividualBenefit(individualBenefit: InnerIndividualBenefit): T fun visitBatchError(batchError: BatchError): T @@ -380,8 +430,8 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - Body(unionMember0 = it, _json = json) + tryDeserialize(node, jacksonTypeRef())?.let { + Body(individualBenefit = it, _json = json) }, tryDeserialize(node, jacksonTypeRef())?.let { Body(batchError = it, _json = json) @@ -411,7 +461,8 @@ private constructor( provider: SerializerProvider, ) { when { - value.unionMember0 != null -> generator.writeObject(value.unionMember0) + value.individualBenefit != null -> + generator.writeObject(value.individualBenefit) value.batchError != null -> generator.writeObject(value.batchError) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid Body") @@ -419,7 +470,7 @@ private constructor( } } - class UnionMember0 + class InnerIndividualBenefit @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val annualMaximum: JsonField, @@ -565,7 +616,8 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember0]. + * Returns a mutable builder for constructing an instance of + * [InnerIndividualBenefit]. * * The following fields are required: * ```java @@ -578,7 +630,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember0]. */ + /** A builder for [InnerIndividualBenefit]. */ class Builder internal constructor() { private var annualMaximum: JsonField? = null @@ -589,13 +641,14 @@ private constructor( private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(unionMember0: UnionMember0) = apply { - annualMaximum = unionMember0.annualMaximum - catchUp = unionMember0.catchUp - companyContribution = unionMember0.companyContribution - employeeDeduction = unionMember0.employeeDeduction - hsaContributionLimit = unionMember0.hsaContributionLimit - additionalProperties = unionMember0.additionalProperties.toMutableMap() + internal fun from(innerIndividualBenefit: InnerIndividualBenefit) = apply { + annualMaximum = innerIndividualBenefit.annualMaximum + catchUp = innerIndividualBenefit.catchUp + companyContribution = innerIndividualBenefit.companyContribution + employeeDeduction = innerIndividualBenefit.employeeDeduction + hsaContributionLimit = innerIndividualBenefit.hsaContributionLimit + additionalProperties = + innerIndividualBenefit.additionalProperties.toMutableMap() } /** @@ -680,24 +733,24 @@ private constructor( /** * Alias for calling [companyContribution] with - * `CompanyContribution.ofInnerUnionMember0(innerUnionMember0)`. + * `CompanyContribution.ofFixed(fixed)`. */ - fun companyContribution(innerUnionMember0: CompanyContribution.InnerUnionMember0) = - companyContribution(CompanyContribution.ofInnerUnionMember0(innerUnionMember0)) + fun companyContribution(fixed: CompanyContribution.CompanyContributionFixed) = + companyContribution(CompanyContribution.ofFixed(fixed)) /** * Alias for calling [companyContribution] with - * `CompanyContribution.ofUnionMember1(unionMember1)`. + * `CompanyContribution.ofPercent(percent)`. */ - fun companyContribution(unionMember1: CompanyContribution.UnionMember1) = - companyContribution(CompanyContribution.ofUnionMember1(unionMember1)) + fun companyContribution(percent: CompanyContribution.CompanyContributionPercent) = + companyContribution(CompanyContribution.ofPercent(percent)) /** * Alias for calling [companyContribution] with - * `CompanyContribution.ofUnionMember2(unionMember2)`. + * `CompanyContribution.ofTiered(tiered)`. */ - fun companyContribution(unionMember2: CompanyContribution.UnionMember2) = - companyContribution(CompanyContribution.ofUnionMember2(unionMember2)) + fun companyContribution(tiered: CompanyContribution.CompanyContributionTiered) = + companyContribution(CompanyContribution.ofTiered(tiered)) /** * Employee deduction configuration. Supports both fixed amounts (in cents) and @@ -726,17 +779,19 @@ private constructor( /** * Alias for calling [employeeDeduction] with - * `EmployeeDeduction.ofInnerUnionMember0(innerUnionMember0)`. + * `EmployeeDeduction.ofContributionFixed(contributionFixed)`. */ - fun employeeDeduction(innerUnionMember0: EmployeeDeduction.InnerUnionMember0) = - employeeDeduction(EmployeeDeduction.ofInnerUnionMember0(innerUnionMember0)) + fun employeeDeduction( + contributionFixed: EmployeeDeduction.EmployeeDeductionContributionFixed + ) = employeeDeduction(EmployeeDeduction.ofContributionFixed(contributionFixed)) /** * Alias for calling [employeeDeduction] with - * `EmployeeDeduction.ofUnionMember1(unionMember1)`. + * `EmployeeDeduction.ofContributionPercent(contributionPercent)`. */ - fun employeeDeduction(unionMember1: EmployeeDeduction.UnionMember1) = - employeeDeduction(EmployeeDeduction.ofUnionMember1(unionMember1)) + fun employeeDeduction( + contributionPercent: EmployeeDeduction.EmployeeDeductionContributionPercent + ) = employeeDeduction(EmployeeDeduction.ofContributionPercent(contributionPercent)) /** Type for HSA contribution limit if the benefit is a HSA. */ fun hsaContributionLimit(hsaContributionLimit: HsaContributionLimit?) = @@ -784,7 +839,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember0]. + * Returns an immutable instance of [InnerIndividualBenefit]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -798,8 +853,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember0 = - UnionMember0( + fun build(): InnerIndividualBenefit = + InnerIndividualBenefit( checkRequired("annualMaximum", annualMaximum), checkRequired("catchUp", catchUp), checkRequired("companyContribution", companyContribution), @@ -811,7 +866,17 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember0 = apply { + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): InnerIndividualBenefit = apply { if (validated) { return@apply } @@ -855,45 +920,82 @@ private constructor( @JsonSerialize(using = CompanyContribution.Serializer::class) class CompanyContribution private constructor( - private val innerUnionMember0: InnerUnionMember0? = null, - private val unionMember1: UnionMember1? = null, - private val unionMember2: UnionMember2? = null, + private val fixed: CompanyContributionFixed? = null, + private val percent: CompanyContributionPercent? = null, + private val tiered: CompanyContributionTiered? = null, private val _json: JsonValue? = null, ) { - fun innerUnionMember0(): Optional = - Optional.ofNullable(innerUnionMember0) + fun fixed(): Optional = Optional.ofNullable(fixed) - fun unionMember1(): Optional = Optional.ofNullable(unionMember1) + fun percent(): Optional = Optional.ofNullable(percent) - fun unionMember2(): Optional = Optional.ofNullable(unionMember2) + fun tiered(): Optional = Optional.ofNullable(tiered) - fun isInnerUnionMember0(): Boolean = innerUnionMember0 != null + fun isFixed(): Boolean = fixed != null - fun isUnionMember1(): Boolean = unionMember1 != null + fun isPercent(): Boolean = percent != null - fun isUnionMember2(): Boolean = unionMember2 != null + fun isTiered(): Boolean = tiered != null - fun asInnerUnionMember0(): InnerUnionMember0 = - innerUnionMember0.getOrThrow("innerUnionMember0") + fun asFixed(): CompanyContributionFixed = fixed.getOrThrow("fixed") - fun asUnionMember1(): UnionMember1 = unionMember1.getOrThrow("unionMember1") + fun asPercent(): CompanyContributionPercent = percent.getOrThrow("percent") - fun asUnionMember2(): UnionMember2 = unionMember2.getOrThrow("unionMember2") + fun asTiered(): CompanyContributionTiered = tiered.getOrThrow("tiered") fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = companyContribution.accept(new CompanyContribution.Visitor>() { + * @Override + * public Optional visitFixed(CompanyContributionFixed fixed) { + * return Optional.of(fixed.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { - innerUnionMember0 != null -> - visitor.visitInnerUnionMember0(innerUnionMember0) - unionMember1 != null -> visitor.visitUnionMember1(unionMember1) - unionMember2 != null -> visitor.visitUnionMember2(unionMember2) + fixed != null -> visitor.visitFixed(fixed) + percent != null -> visitor.visitPercent(percent) + tiered != null -> visitor.visitTiered(tiered) else -> visitor.unknown(_json) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): CompanyContribution = apply { if (validated) { return@apply @@ -901,18 +1003,16 @@ private constructor( accept( object : Visitor { - override fun visitInnerUnionMember0( - innerUnionMember0: InnerUnionMember0 - ) { - innerUnionMember0.validate() + override fun visitFixed(fixed: CompanyContributionFixed) { + fixed.validate() } - override fun visitUnionMember1(unionMember1: UnionMember1) { - unionMember1.validate() + override fun visitPercent(percent: CompanyContributionPercent) { + percent.validate() } - override fun visitUnionMember2(unionMember2: UnionMember2) { - unionMember2.validate() + override fun visitTiered(tiered: CompanyContributionTiered) { + tiered.validate() } } ) @@ -937,15 +1037,14 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitInnerUnionMember0( - innerUnionMember0: InnerUnionMember0 - ) = innerUnionMember0.validity() + override fun visitFixed(fixed: CompanyContributionFixed) = + fixed.validity() - override fun visitUnionMember1(unionMember1: UnionMember1) = - unionMember1.validity() + override fun visitPercent(percent: CompanyContributionPercent) = + percent.validity() - override fun visitUnionMember2(unionMember2: UnionMember2) = - unionMember2.validity() + override fun visitTiered(tiered: CompanyContributionTiered) = + tiered.validity() override fun unknown(json: JsonValue?) = 0 } @@ -957,20 +1056,18 @@ private constructor( } return other is CompanyContribution && - innerUnionMember0 == other.innerUnionMember0 && - unionMember1 == other.unionMember1 && - unionMember2 == other.unionMember2 + fixed == other.fixed && + percent == other.percent && + tiered == other.tiered } - override fun hashCode(): Int = - Objects.hash(innerUnionMember0, unionMember1, unionMember2) + override fun hashCode(): Int = Objects.hash(fixed, percent, tiered) override fun toString(): String = when { - innerUnionMember0 != null -> - "CompanyContribution{innerUnionMember0=$innerUnionMember0}" - unionMember1 != null -> "CompanyContribution{unionMember1=$unionMember1}" - unionMember2 != null -> "CompanyContribution{unionMember2=$unionMember2}" + fixed != null -> "CompanyContribution{fixed=$fixed}" + percent != null -> "CompanyContribution{percent=$percent}" + tiered != null -> "CompanyContribution{tiered=$tiered}" _json != null -> "CompanyContribution{_unknown=$_json}" else -> throw IllegalStateException("Invalid CompanyContribution") } @@ -978,16 +1075,16 @@ private constructor( companion object { @JvmStatic - fun ofInnerUnionMember0(innerUnionMember0: InnerUnionMember0) = - CompanyContribution(innerUnionMember0 = innerUnionMember0) + fun ofFixed(fixed: CompanyContributionFixed) = + CompanyContribution(fixed = fixed) @JvmStatic - fun ofUnionMember1(unionMember1: UnionMember1) = - CompanyContribution(unionMember1 = unionMember1) + fun ofPercent(percent: CompanyContributionPercent) = + CompanyContribution(percent = percent) @JvmStatic - fun ofUnionMember2(unionMember2: UnionMember2) = - CompanyContribution(unionMember2 = unionMember2) + fun ofTiered(tiered: CompanyContributionTiered) = + CompanyContribution(tiered = tiered) } /** @@ -996,11 +1093,11 @@ private constructor( */ interface Visitor { - fun visitInnerUnionMember0(innerUnionMember0: InnerUnionMember0): T + fun visitFixed(fixed: CompanyContributionFixed): T - fun visitUnionMember1(unionMember1: UnionMember1): T + fun visitPercent(percent: CompanyContributionPercent): T - fun visitUnionMember2(unionMember2: UnionMember2): T + fun visitTiered(tiered: CompanyContributionTiered): T /** * Maps an unknown variant of [CompanyContribution] to a value of type [T]. @@ -1025,15 +1122,18 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - CompanyContribution(innerUnionMember0 = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - CompanyContribution(unionMember1 = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - CompanyContribution(unionMember2 = it, _json = json) - }, + tryDeserialize(node, jacksonTypeRef()) + ?.let { CompanyContribution(fixed = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { CompanyContribution(percent = it, _json = json) }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { CompanyContribution(tiered = it, _json = json) }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -1061,17 +1161,16 @@ private constructor( provider: SerializerProvider, ) { when { - value.innerUnionMember0 != null -> - generator.writeObject(value.innerUnionMember0) - value.unionMember1 != null -> generator.writeObject(value.unionMember1) - value.unionMember2 != null -> generator.writeObject(value.unionMember2) + value.fixed != null -> generator.writeObject(value.fixed) + value.percent != null -> generator.writeObject(value.percent) + value.tiered != null -> generator.writeObject(value.tiered) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid CompanyContribution") } } } - class InnerUnionMember0 + class CompanyContributionFixed @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, @@ -1141,7 +1240,7 @@ private constructor( /** * Returns a mutable builder for constructing an instance of - * [InnerUnionMember0]. + * [CompanyContributionFixed]. * * The following fields are required: * ```java @@ -1152,7 +1251,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [InnerUnionMember0]. */ + /** A builder for [CompanyContributionFixed]. */ class Builder internal constructor() { private var amount: JsonField? = null @@ -1161,12 +1260,13 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(innerUnionMember0: InnerUnionMember0) = apply { - amount = innerUnionMember0.amount - type = innerUnionMember0.type - additionalProperties = - innerUnionMember0.additionalProperties.toMutableMap() - } + internal fun from(companyContributionFixed: CompanyContributionFixed) = + apply { + amount = companyContributionFixed.amount + type = companyContributionFixed.type + additionalProperties = + companyContributionFixed.additionalProperties.toMutableMap() + } /** * Contribution amount in cents (for type=fixed) or basis points (for @@ -1221,7 +1321,7 @@ private constructor( } /** - * Returns an immutable instance of [InnerUnionMember0]. + * Returns an immutable instance of [CompanyContributionFixed]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -1233,8 +1333,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): InnerUnionMember0 = - InnerUnionMember0( + fun build(): CompanyContributionFixed = + CompanyContributionFixed( checkRequired("amount", amount), checkRequired("type", type), additionalProperties.toMutableMap(), @@ -1243,7 +1343,17 @@ private constructor( private var validated: Boolean = false - fun validate(): InnerUnionMember0 = apply { + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): CompanyContributionFixed = apply { if (validated) { return@apply } @@ -1366,6 +1476,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1410,7 +1530,7 @@ private constructor( return true } - return other is InnerUnionMember0 && + return other is CompanyContributionFixed && amount == other.amount && type == other.type && additionalProperties == other.additionalProperties @@ -1423,10 +1543,10 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "InnerUnionMember0{amount=$amount, type=$type, additionalProperties=$additionalProperties}" + "CompanyContributionFixed{amount=$amount, type=$type, additionalProperties=$additionalProperties}" } - class UnionMember1 + class CompanyContributionPercent @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, @@ -1495,7 +1615,8 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember1]. + * Returns a mutable builder for constructing an instance of + * [CompanyContributionPercent]. * * The following fields are required: * ```java @@ -1506,7 +1627,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember1]. */ + /** A builder for [CompanyContributionPercent]. */ class Builder internal constructor() { private var amount: JsonField? = null @@ -1515,11 +1636,13 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(unionMember1: UnionMember1) = apply { - amount = unionMember1.amount - type = unionMember1.type - additionalProperties = unionMember1.additionalProperties.toMutableMap() - } + internal fun from(companyContributionPercent: CompanyContributionPercent) = + apply { + amount = companyContributionPercent.amount + type = companyContributionPercent.type + additionalProperties = + companyContributionPercent.additionalProperties.toMutableMap() + } /** * Contribution amount in cents (for type=fixed) or basis points (for @@ -1574,7 +1697,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember1]. + * Returns an immutable instance of [CompanyContributionPercent]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -1586,8 +1709,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember1 = - UnionMember1( + fun build(): CompanyContributionPercent = + CompanyContributionPercent( checkRequired("amount", amount), checkRequired("type", type), additionalProperties.toMutableMap(), @@ -1596,7 +1719,17 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember1 = apply { + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): CompanyContributionPercent = apply { if (validated) { return@apply } @@ -1719,6 +1852,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1763,7 +1906,7 @@ private constructor( return true } - return other is UnionMember1 && + return other is CompanyContributionPercent && amount == other.amount && type == other.type && additionalProperties == other.additionalProperties @@ -1776,10 +1919,10 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember1{amount=$amount, type=$type, additionalProperties=$additionalProperties}" + "CompanyContributionPercent{amount=$amount, type=$type, additionalProperties=$additionalProperties}" } - class UnionMember2 + class CompanyContributionTiered @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val tiers: JsonField>, @@ -1850,7 +1993,8 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember2]. + * Returns a mutable builder for constructing an instance of + * [CompanyContributionTiered]. * * The following fields are required: * ```java @@ -1861,7 +2005,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember2]. */ + /** A builder for [CompanyContributionTiered]. */ class Builder internal constructor() { private var tiers: JsonField>? = null @@ -1870,11 +2014,13 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(unionMember2: UnionMember2) = apply { - tiers = unionMember2.tiers.map { it.toMutableList() } - type = unionMember2.type - additionalProperties = unionMember2.additionalProperties.toMutableMap() - } + internal fun from(companyContributionTiered: CompanyContributionTiered) = + apply { + tiers = companyContributionTiered.tiers.map { it.toMutableList() } + type = companyContributionTiered.type + additionalProperties = + companyContributionTiered.additionalProperties.toMutableMap() + } /** * Array of tier objects defining employer match tiers based on employee @@ -1944,7 +2090,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember2]. + * Returns an immutable instance of [CompanyContributionTiered]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -1956,8 +2102,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember2 = - UnionMember2( + fun build(): CompanyContributionTiered = + CompanyContributionTiered( checkRequired("tiers", tiers).map { it.toImmutable() }, checkRequired("type", type), additionalProperties.toMutableMap(), @@ -1966,7 +2112,17 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember2 = apply { + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): CompanyContributionTiered = apply { if (validated) { return@apply } @@ -2156,6 +2312,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Tier = apply { if (validated) { return@apply @@ -2300,6 +2466,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2344,7 +2520,7 @@ private constructor( return true } - return other is UnionMember2 && + return other is CompanyContributionTiered && tiers == other.tiers && type == other.type && additionalProperties == other.additionalProperties @@ -2357,7 +2533,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember2{tiers=$tiers, type=$type, additionalProperties=$additionalProperties}" + "CompanyContributionTiered{tiers=$tiers, type=$type, additionalProperties=$additionalProperties}" } } @@ -2369,37 +2545,80 @@ private constructor( @JsonSerialize(using = EmployeeDeduction.Serializer::class) class EmployeeDeduction private constructor( - private val innerUnionMember0: InnerUnionMember0? = null, - private val unionMember1: UnionMember1? = null, + private val contributionFixed: EmployeeDeductionContributionFixed? = null, + private val contributionPercent: EmployeeDeductionContributionPercent? = null, private val _json: JsonValue? = null, ) { - fun innerUnionMember0(): Optional = - Optional.ofNullable(innerUnionMember0) + fun contributionFixed(): Optional = + Optional.ofNullable(contributionFixed) - fun unionMember1(): Optional = Optional.ofNullable(unionMember1) + fun contributionPercent(): Optional = + Optional.ofNullable(contributionPercent) - fun isInnerUnionMember0(): Boolean = innerUnionMember0 != null + fun isContributionFixed(): Boolean = contributionFixed != null - fun isUnionMember1(): Boolean = unionMember1 != null + fun isContributionPercent(): Boolean = contributionPercent != null - fun asInnerUnionMember0(): InnerUnionMember0 = - innerUnionMember0.getOrThrow("innerUnionMember0") + fun asContributionFixed(): EmployeeDeductionContributionFixed = + contributionFixed.getOrThrow("contributionFixed") - fun asUnionMember1(): UnionMember1 = unionMember1.getOrThrow("unionMember1") + fun asContributionPercent(): EmployeeDeductionContributionPercent = + contributionPercent.getOrThrow("contributionPercent") fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = employeeDeduction.accept(new EmployeeDeduction.Visitor>() { + * @Override + * public Optional visitContributionFixed(EmployeeDeductionContributionFixed contributionFixed) { + * return Optional.of(contributionFixed.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { - innerUnionMember0 != null -> - visitor.visitInnerUnionMember0(innerUnionMember0) - unionMember1 != null -> visitor.visitUnionMember1(unionMember1) + contributionFixed != null -> + visitor.visitContributionFixed(contributionFixed) + contributionPercent != null -> + visitor.visitContributionPercent(contributionPercent) else -> visitor.unknown(_json) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): EmployeeDeduction = apply { if (validated) { return@apply @@ -2407,14 +2626,16 @@ private constructor( accept( object : Visitor { - override fun visitInnerUnionMember0( - innerUnionMember0: InnerUnionMember0 + override fun visitContributionFixed( + contributionFixed: EmployeeDeductionContributionFixed ) { - innerUnionMember0.validate() + contributionFixed.validate() } - override fun visitUnionMember1(unionMember1: UnionMember1) { - unionMember1.validate() + override fun visitContributionPercent( + contributionPercent: EmployeeDeductionContributionPercent + ) { + contributionPercent.validate() } } ) @@ -2439,12 +2660,13 @@ private constructor( internal fun validity(): Int = accept( object : Visitor { - override fun visitInnerUnionMember0( - innerUnionMember0: InnerUnionMember0 - ) = innerUnionMember0.validity() + override fun visitContributionFixed( + contributionFixed: EmployeeDeductionContributionFixed + ) = contributionFixed.validity() - override fun visitUnionMember1(unionMember1: UnionMember1) = - unionMember1.validity() + override fun visitContributionPercent( + contributionPercent: EmployeeDeductionContributionPercent + ) = contributionPercent.validity() override fun unknown(json: JsonValue?) = 0 } @@ -2456,17 +2678,18 @@ private constructor( } return other is EmployeeDeduction && - innerUnionMember0 == other.innerUnionMember0 && - unionMember1 == other.unionMember1 + contributionFixed == other.contributionFixed && + contributionPercent == other.contributionPercent } - override fun hashCode(): Int = Objects.hash(innerUnionMember0, unionMember1) + override fun hashCode(): Int = Objects.hash(contributionFixed, contributionPercent) override fun toString(): String = when { - innerUnionMember0 != null -> - "EmployeeDeduction{innerUnionMember0=$innerUnionMember0}" - unionMember1 != null -> "EmployeeDeduction{unionMember1=$unionMember1}" + contributionFixed != null -> + "EmployeeDeduction{contributionFixed=$contributionFixed}" + contributionPercent != null -> + "EmployeeDeduction{contributionPercent=$contributionPercent}" _json != null -> "EmployeeDeduction{_unknown=$_json}" else -> throw IllegalStateException("Invalid EmployeeDeduction") } @@ -2474,12 +2697,13 @@ private constructor( companion object { @JvmStatic - fun ofInnerUnionMember0(innerUnionMember0: InnerUnionMember0) = - EmployeeDeduction(innerUnionMember0 = innerUnionMember0) + fun ofContributionFixed(contributionFixed: EmployeeDeductionContributionFixed) = + EmployeeDeduction(contributionFixed = contributionFixed) @JvmStatic - fun ofUnionMember1(unionMember1: UnionMember1) = - EmployeeDeduction(unionMember1 = unionMember1) + fun ofContributionPercent( + contributionPercent: EmployeeDeductionContributionPercent + ) = EmployeeDeduction(contributionPercent = contributionPercent) } /** @@ -2488,9 +2712,13 @@ private constructor( */ interface Visitor { - fun visitInnerUnionMember0(innerUnionMember0: InnerUnionMember0): T + fun visitContributionFixed( + contributionFixed: EmployeeDeductionContributionFixed + ): T - fun visitUnionMember1(unionMember1: UnionMember1): T + fun visitContributionPercent( + contributionPercent: EmployeeDeductionContributionPercent + ): T /** * Maps an unknown variant of [EmployeeDeduction] to a value of type [T]. @@ -2515,12 +2743,23 @@ private constructor( val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - EmployeeDeduction(innerUnionMember0 = it, _json = json) - }, - tryDeserialize(node, jacksonTypeRef())?.let { - EmployeeDeduction(unionMember1 = it, _json = json) - }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + EmployeeDeduction(contributionFixed = it, _json = json) + }, + tryDeserialize( + node, + jacksonTypeRef(), + ) + ?.let { + EmployeeDeduction( + contributionPercent = it, + _json = json, + ) + }, ) .filterNotNull() .allMaxBy { it.validity() } @@ -2548,16 +2787,17 @@ private constructor( provider: SerializerProvider, ) { when { - value.innerUnionMember0 != null -> - generator.writeObject(value.innerUnionMember0) - value.unionMember1 != null -> generator.writeObject(value.unionMember1) + value.contributionFixed != null -> + generator.writeObject(value.contributionFixed) + value.contributionPercent != null -> + generator.writeObject(value.contributionPercent) value._json != null -> generator.writeObject(value._json) else -> throw IllegalStateException("Invalid EmployeeDeduction") } } } - class InnerUnionMember0 + class EmployeeDeductionContributionFixed @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, @@ -2627,7 +2867,7 @@ private constructor( /** * Returns a mutable builder for constructing an instance of - * [InnerUnionMember0]. + * [EmployeeDeductionContributionFixed]. * * The following fields are required: * ```java @@ -2638,7 +2878,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [InnerUnionMember0]. */ + /** A builder for [EmployeeDeductionContributionFixed]. */ class Builder internal constructor() { private var amount: JsonField? = null @@ -2647,11 +2887,14 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(innerUnionMember0: InnerUnionMember0) = apply { - amount = innerUnionMember0.amount - type = innerUnionMember0.type + internal fun from( + employeeDeductionContributionFixed: EmployeeDeductionContributionFixed + ) = apply { + amount = employeeDeductionContributionFixed.amount + type = employeeDeductionContributionFixed.type additionalProperties = - innerUnionMember0.additionalProperties.toMutableMap() + employeeDeductionContributionFixed.additionalProperties + .toMutableMap() } /** @@ -2707,7 +2950,7 @@ private constructor( } /** - * Returns an immutable instance of [InnerUnionMember0]. + * Returns an immutable instance of [EmployeeDeductionContributionFixed]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -2719,8 +2962,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): InnerUnionMember0 = - InnerUnionMember0( + fun build(): EmployeeDeductionContributionFixed = + EmployeeDeductionContributionFixed( checkRequired("amount", amount), checkRequired("type", type), additionalProperties.toMutableMap(), @@ -2729,7 +2972,17 @@ private constructor( private var validated: Boolean = false - fun validate(): InnerUnionMember0 = apply { + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): EmployeeDeductionContributionFixed = apply { if (validated) { return@apply } @@ -2852,6 +3105,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2896,7 +3159,7 @@ private constructor( return true } - return other is InnerUnionMember0 && + return other is EmployeeDeductionContributionFixed && amount == other.amount && type == other.type && additionalProperties == other.additionalProperties @@ -2909,10 +3172,10 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "InnerUnionMember0{amount=$amount, type=$type, additionalProperties=$additionalProperties}" + "EmployeeDeductionContributionFixed{amount=$amount, type=$type, additionalProperties=$additionalProperties}" } - class UnionMember1 + class EmployeeDeductionContributionPercent @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( private val amount: JsonField, @@ -2981,7 +3244,8 @@ private constructor( companion object { /** - * Returns a mutable builder for constructing an instance of [UnionMember1]. + * Returns a mutable builder for constructing an instance of + * [EmployeeDeductionContributionPercent]. * * The following fields are required: * ```java @@ -2992,7 +3256,7 @@ private constructor( @JvmStatic fun builder() = Builder() } - /** A builder for [UnionMember1]. */ + /** A builder for [EmployeeDeductionContributionPercent]. */ class Builder internal constructor() { private var amount: JsonField? = null @@ -3001,10 +3265,15 @@ private constructor( mutableMapOf() @JvmSynthetic - internal fun from(unionMember1: UnionMember1) = apply { - amount = unionMember1.amount - type = unionMember1.type - additionalProperties = unionMember1.additionalProperties.toMutableMap() + internal fun from( + employeeDeductionContributionPercent: + EmployeeDeductionContributionPercent + ) = apply { + amount = employeeDeductionContributionPercent.amount + type = employeeDeductionContributionPercent.type + additionalProperties = + employeeDeductionContributionPercent.additionalProperties + .toMutableMap() } /** @@ -3060,7 +3329,7 @@ private constructor( } /** - * Returns an immutable instance of [UnionMember1]. + * Returns an immutable instance of [EmployeeDeductionContributionPercent]. * * Further updates to this [Builder] will not mutate the returned instance. * @@ -3072,8 +3341,8 @@ private constructor( * * @throws IllegalStateException if any required field is unset. */ - fun build(): UnionMember1 = - UnionMember1( + fun build(): EmployeeDeductionContributionPercent = + EmployeeDeductionContributionPercent( checkRequired("amount", amount), checkRequired("type", type), additionalProperties.toMutableMap(), @@ -3082,7 +3351,17 @@ private constructor( private var validated: Boolean = false - fun validate(): UnionMember1 = apply { + /** + * Validates that the types of all values in this object match their expected + * types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't + * match its expected type. + */ + fun validate(): EmployeeDeductionContributionPercent = apply { if (validated) { return@apply } @@ -3205,6 +3484,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their + * expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for + * existing fields. + * + * @throws FinchInvalidDataException if any value type in this object + * doesn't match its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -3249,7 +3538,7 @@ private constructor( return true } - return other is UnionMember1 && + return other is EmployeeDeductionContributionPercent && amount == other.amount && type == other.type && additionalProperties == other.additionalProperties @@ -3262,7 +3551,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember1{amount=$amount, type=$type, additionalProperties=$additionalProperties}" + "EmployeeDeductionContributionPercent{amount=$amount, type=$type, additionalProperties=$additionalProperties}" } } @@ -3364,6 +3653,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): HsaContributionLimit = apply { if (validated) { return@apply @@ -3407,7 +3706,7 @@ private constructor( return true } - return other is UnionMember0 && + return other is InnerIndividualBenefit && annualMaximum == other.annualMaximum && catchUp == other.catchUp && companyContribution == other.companyContribution && @@ -3430,7 +3729,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "UnionMember0{annualMaximum=$annualMaximum, catchUp=$catchUp, companyContribution=$companyContribution, employeeDeduction=$employeeDeduction, hsaContributionLimit=$hsaContributionLimit, additionalProperties=$additionalProperties}" + "InnerIndividualBenefit{annualMaximum=$annualMaximum, catchUp=$catchUp, companyContribution=$companyContribution, employeeDeduction=$employeeDeduction, hsaContributionLimit=$hsaContributionLimit, additionalProperties=$additionalProperties}" } class BatchError @@ -3650,6 +3949,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BatchError = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEnrolledIdsResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEnrolledIdsResponse.kt index ddac4d7de..dabe54dbf 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEnrolledIdsResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEnrolledIdsResponse.kt @@ -184,6 +184,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): IndividualEnrolledIdsResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEvent.kt index ef09dcaa1..b8b54b8ee 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualEvent.kt @@ -24,6 +24,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -36,17 +37,19 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -75,6 +78,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -116,6 +127,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -162,6 +180,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -171,6 +190,7 @@ private constructor( accountId = individualEvent.accountId companyId = individualEvent.companyId connectionId = individualEvent.connectionId + entityId = individualEvent.entityId data = individualEvent.data eventType = individualEvent.eventType additionalProperties = individualEvent.additionalProperties.toMutableMap() @@ -224,6 +244,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: Data) = data(JsonField.of(data)) /** @@ -282,6 +313,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -290,6 +322,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): IndividualEvent = apply { if (validated) { return@apply @@ -298,6 +338,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -321,6 +362,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -429,6 +471,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -567,6 +618,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -614,17 +674,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "IndividualEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "IndividualEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualInDirectory.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualInDirectory.kt index a58d43d95..1dcff56b2 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualInDirectory.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualInDirectory.kt @@ -365,6 +365,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): IndividualInDirectory = apply { if (validated) { return@apply @@ -505,6 +513,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -662,6 +679,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Manager = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualResponse.kt index 772b0bdab..c8b35a026 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualResponse.kt @@ -128,9 +128,8 @@ private constructor( */ fun body(body: JsonField) = apply { this.body = body } - /** Alias for calling [body] with `Individual.ofUnionMember0(unionMember0)`. */ - fun body(unionMember0: Individual.UnionMember0) = - body(Individual.ofUnionMember0(unionMember0)) + /** Alias for calling [body] with `Individual.ofIndividual(individual)`. */ + fun body(individual: Individual.InnerIndividual) = body(Individual.ofIndividual(individual)) /** Alias for calling [body] with `Individual.ofBatchError(batchError)`. */ fun body(batchError: Individual.BatchError) = body(Individual.ofBatchError(batchError)) @@ -202,6 +201,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): IndividualResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualUpdateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualUpdateResponse.kt index 216506ec2..40112fa18 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualUpdateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/IndividualUpdateResponse.kt @@ -605,6 +605,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): IndividualUpdateResponse = apply { if (validated) { return@apply @@ -781,6 +789,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Email = apply { if (validated) { return@apply @@ -898,6 +915,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1081,6 +1108,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Ethnicity = apply { if (validated) { return@apply @@ -1218,6 +1254,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Gender = apply { if (validated) { return@apply @@ -1385,6 +1430,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PhoneNumber = apply { if (validated) { return@apply @@ -1502,6 +1556,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Introspection.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Introspection.kt index 7dbb43f95..d91974956 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Introspection.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Introspection.kt @@ -886,6 +886,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Introspection = apply { if (validated) { return@apply @@ -1041,6 +1049,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ClientType = apply { if (validated) { return@apply @@ -1286,6 +1303,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ConnectionStatusDetail = apply { if (validated) { return@apply @@ -1341,6 +1367,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, + * unless [visitor] overrides [Visitor.unknown]. To handle variants not known to this + * version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = lastSuccessfulSync.accept(new LastSuccessfulSync.Visitor>() { + * @Override + * public Optional visitOffsetDateTime(OffsetDateTime offsetDateTime) { + * return Optional.of(offsetDateTime.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { offsetDateTime != null -> visitor.visitOffsetDateTime(offsetDateTime) @@ -1350,6 +1406,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): LastSuccessfulSync = apply { if (validated) { return@apply @@ -1611,6 +1677,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ConnectionType = apply { if (validated) { return@apply @@ -1855,6 +1930,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationMethodDetail = apply { if (validated) { return@apply @@ -1994,6 +2078,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2248,6 +2342,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ConnectionStatusDetail = apply { if (validated) { return@apply @@ -2303,6 +2407,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the + * API, unless [visitor] overrides [Visitor.unknown]. To handle variants not known + * to this version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = lastSuccessfulSync.accept(new LastSuccessfulSync.Visitor>() { + * @Override + * public Optional visitOffsetDateTime(OffsetDateTime offsetDateTime) { + * return Optional.of(offsetDateTime.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in + * [visitor] and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { offsetDateTime != null -> visitor.visitOffsetDateTime(offsetDateTime) @@ -2312,6 +2446,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): LastSuccessfulSync = apply { if (validated) { return@apply @@ -2509,6 +2653,7 @@ private constructor( private val id: JsonField, private val name: JsonField, private val sourceId: JsonField, + private val status: JsonField, private val additionalProperties: MutableMap, ) { @@ -2519,7 +2664,10 @@ private constructor( @JsonProperty("source_id") @ExcludeMissing sourceId: JsonField = JsonMissing.of(), - ) : this(id, name, sourceId, mutableMapOf()) + @JsonProperty("status") + @ExcludeMissing + status: JsonField = JsonMissing.of(), + ) : this(id, name, sourceId, status, mutableMapOf()) /** * The connection account ID for this entity @@ -2545,6 +2693,14 @@ private constructor( */ fun sourceId(): Optional = sourceId.getOptional("source_id") + /** + * The status of the entity connection + * + * @throws FinchInvalidDataException 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 status(): EntityConnectionStatus = status.getRequired("status") + /** * Returns the raw JSON value of [id]. * @@ -2566,6 +2722,15 @@ private constructor( */ @JsonProperty("source_id") @ExcludeMissing fun _sourceId(): JsonField = sourceId + /** + * Returns the raw JSON value of [status]. + * + * Unlike [status], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("status") + @ExcludeMissing + fun _status(): JsonField = status + @JsonAnySetter private fun putAdditionalProperty(key: String, value: JsonValue) { additionalProperties.put(key, value) @@ -2588,6 +2753,7 @@ private constructor( * .id() * .name() * .sourceId() + * .status() * ``` */ @JvmStatic fun builder() = Builder() @@ -2599,6 +2765,7 @@ private constructor( private var id: JsonField? = null private var name: JsonField? = null private var sourceId: JsonField? = null + private var status: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2606,6 +2773,7 @@ private constructor( id = multiAccountEntity.id name = multiAccountEntity.name sourceId = multiAccountEntity.sourceId + status = multiAccountEntity.status additionalProperties = multiAccountEntity.additionalProperties.toMutableMap() } @@ -2651,6 +2819,18 @@ private constructor( */ fun sourceId(sourceId: JsonField) = apply { this.sourceId = sourceId } + /** The status of the entity connection */ + fun status(status: EntityConnectionStatus) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [EntityConnectionStatus] + * value instead. This method is primarily for setting the field to an undocumented or + * not yet supported value. + */ + fun status(status: JsonField) = apply { this.status = status } + fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -2680,6 +2860,7 @@ private constructor( * .id() * .name() * .sourceId() + * .status() * ``` * * @throws IllegalStateException if any required field is unset. @@ -2689,12 +2870,22 @@ private constructor( checkRequired("id", id), checkRequired("name", name), checkRequired("sourceId", sourceId), + checkRequired("status", status), additionalProperties.toMutableMap(), ) } private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): MultiAccountEntity = apply { if (validated) { return@apply @@ -2703,6 +2894,7 @@ private constructor( id() name() sourceId() + status().validate() validated = true } @@ -2724,7 +2916,184 @@ private constructor( internal fun validity(): Int = (if (id.asKnown().isPresent) 1 else 0) + (if (name.asKnown().isPresent) 1 else 0) + - (if (sourceId.asKnown().isPresent) 1 else 0) + (if (sourceId.asKnown().isPresent) 1 else 0) + + (status.asKnown().getOrNull()?.validity() ?: 0) + + /** The status of the entity connection */ + class EntityConnectionStatus + @JsonCreator + private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val PENDING = of("pending") + + @JvmField val PROCESSING = of("processing") + + @JvmField val CONNECTED = of("connected") + + @JvmField val ERROR_NO_ACCOUNT_SETUP = of("error_no_account_setup") + + @JvmField val ERROR_PERMISSIONS = of("error_permissions") + + @JvmField val REAUTH = of("reauth") + + @JvmField val DISCONNECTED = of("disconnected") + + @JvmStatic fun of(value: String) = EntityConnectionStatus(JsonField.of(value)) + } + + /** An enum containing [EntityConnectionStatus]'s known values. */ + enum class Known { + PENDING, + PROCESSING, + CONNECTED, + ERROR_NO_ACCOUNT_SETUP, + ERROR_PERMISSIONS, + REAUTH, + DISCONNECTED, + } + + /** + * An enum containing [EntityConnectionStatus]'s known values, as well as an [_UNKNOWN] + * member. + * + * An instance of [EntityConnectionStatus] 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 { + PENDING, + PROCESSING, + CONNECTED, + ERROR_NO_ACCOUNT_SETUP, + ERROR_PERMISSIONS, + REAUTH, + DISCONNECTED, + /** + * An enum member indicating that [EntityConnectionStatus] 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) { + PENDING -> Value.PENDING + PROCESSING -> Value.PROCESSING + CONNECTED -> Value.CONNECTED + ERROR_NO_ACCOUNT_SETUP -> Value.ERROR_NO_ACCOUNT_SETUP + ERROR_PERMISSIONS -> Value.ERROR_PERMISSIONS + REAUTH -> Value.REAUTH + DISCONNECTED -> Value.DISCONNECTED + 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 FinchInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + PENDING -> Known.PENDING + PROCESSING -> Known.PROCESSING + CONNECTED -> Known.CONNECTED + ERROR_NO_ACCOUNT_SETUP -> Known.ERROR_NO_ACCOUNT_SETUP + ERROR_PERMISSIONS -> Known.ERROR_PERMISSIONS + REAUTH -> Known.REAUTH + DISCONNECTED -> Known.DISCONNECTED + else -> + throw FinchInvalidDataException("Unknown EntityConnectionStatus: $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 FinchInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + FinchInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): EntityConnectionStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: FinchInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is EntityConnectionStatus && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } override fun equals(other: Any?): Boolean { if (this === other) { @@ -2735,15 +3104,18 @@ private constructor( id == other.id && name == other.name && sourceId == other.sourceId && + status == other.status && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(id, name, sourceId, additionalProperties) } + private val hashCode: Int by lazy { + Objects.hash(id, name, sourceId, status, additionalProperties) + } override fun hashCode(): Int = hashCode override fun toString() = - "MultiAccountEntity{id=$id, name=$name, sourceId=$sourceId, additionalProperties=$additionalProperties}" + "MultiAccountEntity{id=$id, name=$name, sourceId=$sourceId, status=$status, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobAutomatedCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobAutomatedCreateParams.kt index 10922d083..fa18ecf9d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobAutomatedCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobAutomatedCreateParams.kt @@ -47,12 +47,12 @@ import kotlin.jvm.optionals.getOrNull */ class JobAutomatedCreateParams private constructor( - private val body: Body?, + private val body: Body, private val additionalHeaders: Headers, private val additionalQueryParams: QueryParams, ) : Params { - fun body(): Optional = Optional.ofNullable(body) + fun body(): Body = body /** Additional headers to send with the request. */ fun _additionalHeaders(): Headers = additionalHeaders @@ -64,9 +64,14 @@ private constructor( companion object { - @JvmStatic fun none(): JobAutomatedCreateParams = builder().build() - - /** Returns a mutable builder for constructing an instance of [JobAutomatedCreateParams]. */ + /** + * Returns a mutable builder for constructing an instance of [JobAutomatedCreateParams]. + * + * The following fields are required: + * ```java + * .body() + * ``` + */ @JvmStatic fun builder() = Builder() } @@ -84,10 +89,7 @@ private constructor( additionalQueryParams = jobAutomatedCreateParams.additionalQueryParams.toBuilder() } - fun body(body: Body?) = apply { this.body = body } - - /** Alias for calling [Builder.body] with `body.orElse(null)`. */ - fun body(body: Optional) = body(body.getOrNull()) + fun body(body: Body) = apply { this.body = body } /** Alias for calling [body] with `Body.ofDataSyncAll()`. */ fun bodyDataSyncAll() = body(Body.ofDataSyncAll()) @@ -209,12 +211,23 @@ private constructor( * Returns an immutable instance of [JobAutomatedCreateParams]. * * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ fun build(): JobAutomatedCreateParams = - JobAutomatedCreateParams(body, additionalHeaders.build(), additionalQueryParams.build()) + JobAutomatedCreateParams( + checkRequired("body", body), + additionalHeaders.build(), + additionalQueryParams.build(), + ) } - fun _body(): Optional = Optional.ofNullable(body) + fun _body(): Body = body override fun _headers(): Headers = additionalHeaders @@ -245,6 +258,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = body.accept(new Body.Visitor>() { + * @Override + * public Optional visitDataSyncAll(JsonValue dataSyncAll) { + * return Optional.of(dataSyncAll.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { dataSyncAll != null -> visitor.visitDataSyncAll(dataSyncAll) @@ -254,6 +296,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -552,6 +603,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): W4FormEmployeeSync = apply { if (validated) { return@apply @@ -713,6 +774,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Params = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCompletionEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCompletionEvent.kt index 7b47622e9..7a423749b 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCompletionEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCompletionEvent.kt @@ -24,6 +24,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -36,17 +37,19 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -75,6 +78,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -116,6 +127,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -162,6 +180,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -171,6 +190,7 @@ private constructor( accountId = jobCompletionEvent.accountId companyId = jobCompletionEvent.companyId connectionId = jobCompletionEvent.connectionId + entityId = jobCompletionEvent.entityId data = jobCompletionEvent.data eventType = jobCompletionEvent.eventType additionalProperties = jobCompletionEvent.additionalProperties.toMutableMap() @@ -224,6 +244,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: Data) = data(JsonField.of(data)) /** @@ -282,6 +313,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -290,6 +322,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): JobCompletionEvent = apply { if (validated) { return@apply @@ -298,6 +338,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -321,6 +362,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -474,6 +516,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -547,6 +598,16 @@ private constructor( @JvmField val JOB_DATA_SYNC_ALL_COMPLETED = of("job.data_sync_all.completed") + @JvmField + val JOB_W4_FORM_EMPLOYEE_SYNC_COMPLETED = of("job.w4_form_employee_sync.completed") + + @JvmField + val JOB_INITIAL_DATA_SYNC_ORG_SUCCEEDED = of("job.initial_data_sync_org.succeeded") + + @JvmField + val JOB_INITIAL_DATA_SYNC_PAYROLL_SUCCEEDED = + of("job.initial_data_sync_payroll.succeeded") + @JvmStatic fun of(value: String) = EventType(JsonField.of(value)) } @@ -558,6 +619,9 @@ private constructor( JOB_BENEFIT_UNENROLL_COMPLETED, JOB_BENEFIT_UPDATE_COMPLETED, JOB_DATA_SYNC_ALL_COMPLETED, + JOB_W4_FORM_EMPLOYEE_SYNC_COMPLETED, + JOB_INITIAL_DATA_SYNC_ORG_SUCCEEDED, + JOB_INITIAL_DATA_SYNC_PAYROLL_SUCCEEDED, } /** @@ -576,6 +640,9 @@ private constructor( JOB_BENEFIT_UNENROLL_COMPLETED, JOB_BENEFIT_UPDATE_COMPLETED, JOB_DATA_SYNC_ALL_COMPLETED, + JOB_W4_FORM_EMPLOYEE_SYNC_COMPLETED, + JOB_INITIAL_DATA_SYNC_ORG_SUCCEEDED, + JOB_INITIAL_DATA_SYNC_PAYROLL_SUCCEEDED, /** * An enum member indicating that [EventType] was instantiated with an unknown value. */ @@ -597,6 +664,10 @@ private constructor( JOB_BENEFIT_UNENROLL_COMPLETED -> Value.JOB_BENEFIT_UNENROLL_COMPLETED JOB_BENEFIT_UPDATE_COMPLETED -> Value.JOB_BENEFIT_UPDATE_COMPLETED JOB_DATA_SYNC_ALL_COMPLETED -> Value.JOB_DATA_SYNC_ALL_COMPLETED + JOB_W4_FORM_EMPLOYEE_SYNC_COMPLETED -> Value.JOB_W4_FORM_EMPLOYEE_SYNC_COMPLETED + JOB_INITIAL_DATA_SYNC_ORG_SUCCEEDED -> Value.JOB_INITIAL_DATA_SYNC_ORG_SUCCEEDED + JOB_INITIAL_DATA_SYNC_PAYROLL_SUCCEEDED -> + Value.JOB_INITIAL_DATA_SYNC_PAYROLL_SUCCEEDED else -> Value._UNKNOWN } @@ -616,6 +687,10 @@ private constructor( JOB_BENEFIT_UNENROLL_COMPLETED -> Known.JOB_BENEFIT_UNENROLL_COMPLETED JOB_BENEFIT_UPDATE_COMPLETED -> Known.JOB_BENEFIT_UPDATE_COMPLETED JOB_DATA_SYNC_ALL_COMPLETED -> Known.JOB_DATA_SYNC_ALL_COMPLETED + JOB_W4_FORM_EMPLOYEE_SYNC_COMPLETED -> Known.JOB_W4_FORM_EMPLOYEE_SYNC_COMPLETED + JOB_INITIAL_DATA_SYNC_ORG_SUCCEEDED -> Known.JOB_INITIAL_DATA_SYNC_ORG_SUCCEEDED + JOB_INITIAL_DATA_SYNC_PAYROLL_SUCCEEDED -> + Known.JOB_INITIAL_DATA_SYNC_PAYROLL_SUCCEEDED else -> throw FinchInvalidDataException("Unknown EventType: $value") } @@ -633,6 +708,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -680,17 +764,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "JobCompletionEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "JobCompletionEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCreateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCreateResponse.kt index 01930c0c9..ab2dcb6f9 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCreateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/JobCreateResponse.kt @@ -247,6 +247,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): JobCreateResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Location.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Location.kt index 5f7a926e2..964db28ac 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Location.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Location.kt @@ -380,6 +380,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Location = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ManualAsyncJob.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ManualAsyncJob.kt index 15b3d1244..05706cc33 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ManualAsyncJob.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ManualAsyncJob.kt @@ -213,6 +213,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): ManualAsyncJob = apply { if (validated) { return@apply @@ -341,6 +349,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Status = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Money.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Money.kt index 7790ef4e5..92b16e8de 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Money.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Money.kt @@ -172,6 +172,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Money = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupport.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupport.kt index 866767523..24f8f9c00 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupport.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupport.kt @@ -116,6 +116,14 @@ class OperationSupport @JsonCreator private constructor(private val value: JsonF private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): OperationSupport = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupportMatrix.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupportMatrix.kt index e66ea860b..8f0cb3230 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupportMatrix.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/OperationSupportMatrix.kt @@ -276,6 +276,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): OperationSupportMatrix = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Paging.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Paging.kt index b1c025ab9..09f8658e1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Paging.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Paging.kt @@ -158,6 +158,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Paging = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupListResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupListResponse.kt index a164bdc42..bd619364b 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupListResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupListResponse.kt @@ -220,6 +220,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayGroupListResponse = apply { if (validated) { return@apply @@ -381,6 +389,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PayFrequency = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupRetrieveResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupRetrieveResponse.kt index acb630a87..408815ffe 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupRetrieveResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayGroupRetrieveResponse.kt @@ -269,6 +269,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayGroupRetrieveResponse = apply { if (validated) { return@apply @@ -432,6 +440,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PayFrequency = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatement.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatement.kt index 00fcc1004..1f3c1750b 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatement.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatement.kt @@ -571,6 +571,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayStatement = apply { if (validated) { return@apply @@ -940,6 +948,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Earning = apply { if (validated) { return@apply @@ -1133,6 +1150,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1301,6 +1328,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -1392,6 +1429,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -1799,6 +1846,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmployeeDeduction = apply { if (validated) { return@apply @@ -1966,6 +2022,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -2057,6 +2123,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -2418,6 +2494,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmployerContribution = apply { if (validated) { return@apply @@ -2583,6 +2668,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -2674,6 +2769,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -2856,6 +2961,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PaymentMethod = apply { if (validated) { return@apply @@ -3215,6 +3329,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tax = apply { if (validated) { return@apply @@ -3354,6 +3477,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -3522,6 +3655,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -3613,6 +3756,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -3792,6 +3945,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementDataSyncInProgress.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementDataSyncInProgress.kt index b28b0965f..1d0d4d040 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementDataSyncInProgress.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementDataSyncInProgress.kt @@ -224,6 +224,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayStatementDataSyncInProgress = apply { if (validated) { return@apply @@ -334,6 +342,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Code = apply { if (validated) { return@apply @@ -454,6 +471,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): FinchCode = apply { if (validated) { return@apply @@ -580,6 +606,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Message = apply { if (validated) { return@apply @@ -698,6 +733,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Name = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementEvent.kt index bd2369e99..d72a840c0 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementEvent.kt @@ -24,6 +24,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -36,17 +37,19 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -75,6 +78,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -116,6 +127,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -162,6 +180,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -171,6 +190,7 @@ private constructor( accountId = payStatementEvent.accountId companyId = payStatementEvent.companyId connectionId = payStatementEvent.connectionId + entityId = payStatementEvent.entityId data = payStatementEvent.data eventType = payStatementEvent.eventType additionalProperties = payStatementEvent.additionalProperties.toMutableMap() @@ -224,6 +244,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: Data) = data(JsonField.of(data)) /** @@ -282,6 +313,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -290,6 +322,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayStatementEvent = apply { if (validated) { return@apply @@ -298,6 +338,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -321,6 +362,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -462,6 +504,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -606,6 +657,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -653,17 +713,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "PayStatementEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "PayStatementEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementItemListResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementItemListResponse.kt index 5c689b69d..b00a17c01 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementItemListResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementItemListResponse.kt @@ -206,6 +206,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayStatementItemListResponse = apply { if (validated) { return@apply @@ -490,6 +498,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -588,6 +605,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -751,6 +778,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Category = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponse.kt index a6b413e65..84a22a8a1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponse.kt @@ -215,6 +215,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayStatementResponse = apply { if (validated) { return@apply @@ -279,6 +287,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of + * the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = body.accept(new Body.Visitor>() { + * @Override + * public Optional visitPayStatementResponse(PayStatementResponseBody payStatementResponse) { + * return Optional.of(payStatementResponse.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and + * the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { payStatementResponse != null -> @@ -291,6 +328,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -681,6 +727,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BatchError = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponseBody.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponseBody.kt index 1469582f7..f3ef5587f 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponseBody.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PayStatementResponseBody.kt @@ -181,6 +181,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PayStatementResponseBody = apply { if (validated) { return@apply @@ -353,6 +361,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Paging = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Payment.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Payment.kt index 9323559f7..d423a801f 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Payment.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Payment.kt @@ -613,6 +613,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Payment = apply { if (validated) { return@apply @@ -792,6 +800,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PayFrequency = apply { if (validated) { return@apply @@ -983,6 +1000,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PayPeriod = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentCreateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentCreateResponse.kt index f7f4ae99a..9100a0cdf 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentCreateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentCreateResponse.kt @@ -164,6 +164,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PaymentCreateResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentEvent.kt index 6191a5f39..2499e4eb0 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/PaymentEvent.kt @@ -24,6 +24,7 @@ private constructor( private val accountId: JsonField, private val companyId: JsonField, private val connectionId: JsonField, + private val entityId: JsonField, private val data: JsonField, private val eventType: JsonField, private val additionalProperties: MutableMap, @@ -36,19 +37,21 @@ private constructor( @JsonProperty("connection_id") @ExcludeMissing connectionId: JsonField = JsonMissing.of(), + @JsonProperty("entity_id") @ExcludeMissing entityId: JsonField = JsonMissing.of(), @JsonProperty("data") @ExcludeMissing data: JsonField = JsonMissing.of(), @JsonProperty("event_type") @ExcludeMissing eventType: JsonField = JsonMissing.of(), - ) : this(accountId, companyId, connectionId, data, eventType, mutableMapOf()) + ) : this(accountId, companyId, connectionId, entityId, data, eventType, mutableMapOf()) fun toBaseWebhookEvent(): BaseWebhookEvent = BaseWebhookEvent.builder() .accountId(accountId) .companyId(companyId) .connectionId(connectionId) + .entityId(entityId) .build() /** @@ -77,6 +80,14 @@ private constructor( */ fun connectionId(): Optional = connectionId.getOptional("connection_id") + /** + * Unique Finch id of the entity for which data has been updated. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun entityId(): Optional = entityId.getOptional("entity_id") + /** * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -118,6 +129,13 @@ private constructor( @ExcludeMissing fun _connectionId(): JsonField = connectionId + /** + * Returns the raw JSON value of [entityId]. + * + * Unlike [entityId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("entity_id") @ExcludeMissing fun _entityId(): JsonField = entityId + /** * Returns the raw JSON value of [data]. * @@ -164,6 +182,7 @@ private constructor( private var accountId: JsonField? = null private var companyId: JsonField? = null private var connectionId: JsonField = JsonMissing.of() + private var entityId: JsonField = JsonMissing.of() private var data: JsonField = JsonMissing.of() private var eventType: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -173,6 +192,7 @@ private constructor( accountId = paymentEvent.accountId companyId = paymentEvent.companyId connectionId = paymentEvent.connectionId + entityId = paymentEvent.entityId data = paymentEvent.data eventType = paymentEvent.eventType additionalProperties = paymentEvent.additionalProperties.toMutableMap() @@ -226,6 +246,17 @@ private constructor( this.connectionId = connectionId } + /** Unique Finch id of the entity for which data has been updated. */ + fun entityId(entityId: String) = entityId(JsonField.of(entityId)) + + /** + * Sets [Builder.entityId] to an arbitrary JSON value. + * + * You should usually call [Builder.entityId] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun entityId(entityId: JsonField) = apply { this.entityId = entityId } + fun data(data: PaymentIdentifiers) = data(JsonField.of(data)) /** @@ -285,6 +316,7 @@ private constructor( checkRequired("accountId", accountId), checkRequired("companyId", companyId), connectionId, + entityId, data, eventType, additionalProperties.toMutableMap(), @@ -293,6 +325,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): PaymentEvent = apply { if (validated) { return@apply @@ -301,6 +341,7 @@ private constructor( accountId() companyId() connectionId() + entityId() data().ifPresent { it.validate() } eventType().ifPresent { it.validate() } validated = true @@ -324,6 +365,7 @@ private constructor( (if (accountId.asKnown().isPresent) 1 else 0) + (if (companyId.asKnown().isPresent) 1 else 0) + (if (connectionId.asKnown().isPresent) 1 else 0) + + (if (entityId.asKnown().isPresent) 1 else 0) + (data.asKnown().getOrNull()?.validity() ?: 0) + (eventType.asKnown().getOrNull()?.validity() ?: 0) @@ -479,6 +521,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PaymentIdentifiers = apply { if (validated) { return@apply @@ -621,6 +672,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EventType = apply { if (validated) { return@apply @@ -668,17 +728,26 @@ private constructor( accountId == other.accountId && companyId == other.companyId && connectionId == other.connectionId && + entityId == other.entityId && data == other.data && eventType == other.eventType && additionalProperties == other.additionalProperties } private val hashCode: Int by lazy { - Objects.hash(accountId, companyId, connectionId, data, eventType, additionalProperties) + Objects.hash( + accountId, + companyId, + connectionId, + entityId, + data, + eventType, + additionalProperties, + ) } override fun hashCode(): Int = hashCode override fun toString() = - "PaymentEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" + "PaymentEvent{accountId=$accountId, companyId=$companyId, connectionId=$connectionId, entityId=$entityId, data=$data, eventType=$eventType, additionalProperties=$additionalProperties}" } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Provider.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Provider.kt index 94ccb0dd4..a7ddf6869 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Provider.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/Provider.kt @@ -497,6 +497,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): Provider = apply { if (validated) { return@apply @@ -739,6 +747,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationMethod = apply { if (validated) { return@apply @@ -884,6 +901,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -984,6 +1011,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BenefitsSupport = apply { if (validated) { return@apply @@ -1088,6 +1125,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SupportedFields = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ProviderListResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ProviderListResponse.kt index 927404e66..3d65eeea0 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ProviderListResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/ProviderListResponse.kt @@ -498,6 +498,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): ProviderListResponse = apply { if (validated) { return@apply @@ -740,6 +748,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationMethod = apply { if (validated) { return@apply @@ -885,6 +902,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -985,6 +1012,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): BenefitsSupport = apply { if (validated) { return@apply @@ -1089,6 +1126,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): SupportedFields = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardParams.kt index 00a1ab35b..f8bd80df9 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardParams.kt @@ -685,6 +685,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): ForwardRequest = apply { if (validated) { return@apply @@ -806,6 +815,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Params = apply { if (validated) { return@apply @@ -910,6 +928,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): RequestHeaders = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardResponse.kt index a35a91404..6db67bf3b 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RequestForwardingForwardResponse.kt @@ -265,6 +265,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): RequestForwardingForwardResponse = apply { if (validated) { return@apply @@ -565,6 +573,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Request = apply { if (validated) { return@apply @@ -624,6 +641,36 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given + * [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, + * unless [visitor] overrides [Visitor.unknown]. To handle variants not known to this + * version of the SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = data.accept(new Data.Visitor>() { + * @Override + * public Optional visitString(String string) { + * return Optional.of(string.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] + * and the current variant is unknown. + */ fun accept(visitor: Visitor): T = when { string != null -> visitor.visitString(string) @@ -633,6 +680,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -834,6 +891,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): UnionMember1 = apply { if (validated) { return@apply @@ -941,6 +1008,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Headers = apply { if (validated) { return@apply @@ -1044,6 +1121,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Params = apply { if (validated) { return@apply @@ -1171,6 +1258,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Headers = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleCreateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleCreateResponse.kt index c4eb0bbdb..294898c6a 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleCreateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleCreateResponse.kt @@ -445,6 +445,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): RuleCreateResponse = apply { if (validated) { return@apply @@ -592,6 +600,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -683,6 +700,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -905,6 +932,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Condition = apply { if (validated) { return@apply @@ -1023,6 +1059,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply @@ -1166,6 +1212,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EntityType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleDeleteResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleDeleteResponse.kt index 70cb5d141..f0952ac98 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleDeleteResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleDeleteResponse.kt @@ -482,6 +482,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): RuleDeleteResponse = apply { if (validated) { return@apply @@ -631,6 +639,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -722,6 +739,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -944,6 +971,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Condition = apply { if (validated) { return@apply @@ -1062,6 +1098,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply @@ -1205,6 +1251,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EntityType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleListResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleListResponse.kt index c9996f2f6..1f8ffbbfb 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleListResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleListResponse.kt @@ -445,6 +445,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): RuleListResponse = apply { if (validated) { return@apply @@ -592,6 +600,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -683,6 +700,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -905,6 +932,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Condition = apply { if (validated) { return@apply @@ -1023,6 +1059,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply @@ -1166,6 +1212,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EntityType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleUpdateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleUpdateResponse.kt index ad6615d19..8653fbaa4 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleUpdateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/RuleUpdateResponse.kt @@ -445,6 +445,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): RuleUpdateResponse = apply { if (validated) { return@apply @@ -592,6 +600,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Attributes = apply { if (validated) { return@apply @@ -683,6 +700,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Metadata = apply { if (validated) { return@apply @@ -905,6 +932,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Condition = apply { if (validated) { return@apply @@ -1023,6 +1059,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Operator = apply { if (validated) { return@apply @@ -1166,6 +1212,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EntityType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxCompanyUpdateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxCompanyUpdateParams.kt index 00f8cb0be..3251bdf05 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxCompanyUpdateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxCompanyUpdateParams.kt @@ -981,6 +981,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CompanyWithoutId = apply { if (validated) { return@apply @@ -1355,6 +1364,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Account = apply { if (validated) { return@apply @@ -1484,6 +1502,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AccountType = apply { if (validated) { return@apply @@ -1688,6 +1716,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -1822,6 +1859,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Parent = apply { if (validated) { return@apply @@ -2020,6 +2067,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Entity = apply { if (validated) { return@apply @@ -2148,6 +2204,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Subtype = apply { if (validated) { return@apply @@ -2306,6 +2372,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountCreateParams.kt index b6ba61144..414c6b22b 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountCreateParams.kt @@ -592,6 +592,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -751,6 +760,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountUpdateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountUpdateParams.kt index 038170128..29f921c9e 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountUpdateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionAccountUpdateParams.kt @@ -346,6 +346,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionCreateParams.kt index ebb96764a..9f45c73b7 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxConnectionCreateParams.kt @@ -594,6 +594,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -759,6 +768,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): AuthenticationType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParams.kt index 00e2376d6..5fdff3c71 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParams.kt @@ -217,6 +217,7 @@ private constructor( private val endDate: JsonField, private val ethnicity: JsonField, private val firstName: JsonField, + private val flsaStatus: JsonField, private val gender: JsonField, private val income: JsonField, private val incomeHistory: JsonField>, @@ -267,6 +268,9 @@ private constructor( @JsonProperty("first_name") @ExcludeMissing firstName: JsonField = JsonMissing.of(), + @JsonProperty("flsa_status") + @ExcludeMissing + flsaStatus: JsonField = JsonMissing.of(), @JsonProperty("gender") @ExcludeMissing gender: JsonField = JsonMissing.of(), @JsonProperty("income") @ExcludeMissing income: JsonField = JsonMissing.of(), @JsonProperty("income_history") @@ -317,6 +321,7 @@ private constructor( endDate, ethnicity, firstName, + flsaStatus, gender, income, incomeHistory, @@ -422,6 +427,14 @@ private constructor( */ fun firstName(): Optional = firstName.getOptional("first_name") + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun flsaStatus(): Optional = flsaStatus.getOptional("flsa_status") + /** * The gender of the individual. * @@ -637,6 +650,15 @@ private constructor( */ @JsonProperty("first_name") @ExcludeMissing fun _firstName(): JsonField = firstName + /** + * Returns the raw JSON value of [flsaStatus]. + * + * Unlike [flsaStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("flsa_status") + @ExcludeMissing + fun _flsaStatus(): JsonField = flsaStatus + /** * Returns the raw JSON value of [gender]. * @@ -797,6 +819,7 @@ private constructor( private var endDate: JsonField = JsonMissing.of() private var ethnicity: JsonField = JsonMissing.of() private var firstName: JsonField = JsonMissing.of() + private var flsaStatus: JsonField = JsonMissing.of() private var gender: JsonField = JsonMissing.of() private var income: JsonField = JsonMissing.of() private var incomeHistory: JsonField>? = null @@ -828,6 +851,7 @@ private constructor( endDate = individualOrEmployment.endDate ethnicity = individualOrEmployment.ethnicity firstName = individualOrEmployment.firstName + flsaStatus = individualOrEmployment.flsaStatus gender = individualOrEmployment.gender income = individualOrEmployment.income incomeHistory = individualOrEmployment.incomeHistory.map { it.toMutableList() } @@ -1060,6 +1084,26 @@ private constructor( */ fun firstName(firstName: JsonField) = apply { this.firstName = firstName } + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, + * `unknown`. + */ + fun flsaStatus(flsaStatus: FlsaStatus?) = flsaStatus(JsonField.ofNullable(flsaStatus)) + + /** Alias for calling [Builder.flsaStatus] with `flsaStatus.orElse(null)`. */ + fun flsaStatus(flsaStatus: Optional) = flsaStatus(flsaStatus.getOrNull()) + + /** + * Sets [Builder.flsaStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.flsaStatus] with a well-typed [FlsaStatus] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun flsaStatus(flsaStatus: JsonField) = apply { + this.flsaStatus = flsaStatus + } + /** The gender of the individual. */ fun gender(gender: Gender?) = gender(JsonField.ofNullable(gender)) @@ -1389,6 +1433,7 @@ private constructor( endDate, ethnicity, firstName, + flsaStatus, gender, income, (incomeHistory ?: JsonMissing.of()).map { it.toImmutable() }, @@ -1411,6 +1456,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): IndividualOrEmployment = apply { if (validated) { return@apply @@ -1427,6 +1481,7 @@ private constructor( endDate() ethnicity().ifPresent { it.validate() } firstName() + flsaStatus().ifPresent { it.validate() } gender().ifPresent { it.validate() } income().ifPresent { it.validate() } incomeHistory().ifPresent { it.forEach { it?.validate() } } @@ -1473,6 +1528,7 @@ private constructor( (if (endDate.asKnown().isPresent) 1 else 0) + (ethnicity.asKnown().getOrNull()?.validity() ?: 0) + (if (firstName.asKnown().isPresent) 1 else 0) + + (flsaStatus.asKnown().getOrNull()?.validity() ?: 0) + (gender.asKnown().getOrNull()?.validity() ?: 0) + (income.asKnown().getOrNull()?.validity() ?: 0) + (incomeHistory.asKnown().getOrNull()?.sumOf { (it?.validity() ?: 0).toInt() } @@ -1608,6 +1664,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CustomField = apply { if (validated) { return@apply @@ -1757,6 +1823,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -1929,6 +2005,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Email = apply { if (validated) { return@apply @@ -2050,6 +2136,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2253,6 +2349,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Employment = apply { if (validated) { return@apply @@ -2403,6 +2509,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Subtype = apply { if (validated) { return@apply @@ -2534,6 +2650,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2717,6 +2843,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmploymentStatus = apply { if (validated) { return@apply @@ -2887,6 +3023,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Ethnicity = apply { if (validated) { return@apply @@ -2925,6 +3071,156 @@ private constructor( override fun toString() = value.toString() } + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + */ + class FlsaStatus @JsonCreator private constructor(private val value: JsonField) : + Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is + * on an older version than the API, then the API may respond with new members that the + * SDK is unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val EXEMPT = of("exempt") + + @JvmField val NON_EXEMPT = of("non_exempt") + + @JvmField val UNKNOWN = of("unknown") + + @JvmStatic fun of(value: String) = FlsaStatus(JsonField.of(value)) + } + + /** An enum containing [FlsaStatus]'s known values. */ + enum class Known { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + } + + /** + * An enum containing [FlsaStatus]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [FlsaStatus] 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 { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + /** + * An enum member indicating that [FlsaStatus] 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) { + EXEMPT -> Value.EXEMPT + NON_EXEMPT -> Value.NON_EXEMPT + UNKNOWN -> Value.UNKNOWN + 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 FinchInvalidDataException if this class instance's value is a not a known + * member. + */ + fun known(): Known = + when (this) { + EXEMPT -> Known.EXEMPT + NON_EXEMPT -> Known.NON_EXEMPT + UNKNOWN -> Known.UNKNOWN + else -> throw FinchInvalidDataException("Unknown FlsaStatus: $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 FinchInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { + FinchInvalidDataException("Value is not a String") + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): FlsaStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: FinchInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FlsaStatus && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + /** The gender of the individual. */ class Gender @JsonCreator private constructor(private val value: JsonField) : Enum { @@ -3029,6 +3325,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Gender = apply { if (validated) { return@apply @@ -3169,6 +3475,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Manager = apply { if (validated) { return@apply @@ -3344,6 +3660,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PhoneNumber = apply { if (validated) { return@apply @@ -3465,6 +3791,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -3539,6 +3875,7 @@ private constructor( endDate == other.endDate && ethnicity == other.ethnicity && firstName == other.firstName && + flsaStatus == other.flsaStatus && gender == other.gender && income == other.income && incomeHistory == other.incomeHistory && @@ -3571,6 +3908,7 @@ private constructor( endDate, ethnicity, firstName, + flsaStatus, gender, income, incomeHistory, @@ -3594,7 +3932,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "IndividualOrEmployment{classCode=$classCode, customFields=$customFields, department=$department, dob=$dob, emails=$emails, employment=$employment, employmentStatus=$employmentStatus, encryptedSsn=$encryptedSsn, endDate=$endDate, ethnicity=$ethnicity, firstName=$firstName, gender=$gender, income=$income, incomeHistory=$incomeHistory, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, phoneNumbers=$phoneNumbers, preferredName=$preferredName, residence=$residence, sourceId=$sourceId, ssn=$ssn, startDate=$startDate, title=$title, additionalProperties=$additionalProperties}" + "IndividualOrEmployment{classCode=$classCode, customFields=$customFields, department=$department, dob=$dob, emails=$emails, employment=$employment, employmentStatus=$employmentStatus, encryptedSsn=$encryptedSsn, endDate=$endDate, ethnicity=$ethnicity, firstName=$firstName, flsaStatus=$flsaStatus, gender=$gender, income=$income, incomeHistory=$incomeHistory, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, phoneNumbers=$phoneNumbers, preferredName=$preferredName, residence=$residence, sourceId=$sourceId, ssn=$ssn, startDate=$startDate, title=$title, additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParams.kt index 0cf612aa2..03e220e56 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParams.kt @@ -88,6 +88,14 @@ private constructor( */ fun firstName(): Optional = body.firstName() + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun flsaStatus(): Optional = body.flsaStatus() + /** * The employee's income as reported by the provider. This may not always be annualized income, * but may be in units of bi-weekly, semi-monthly, daily, etc, depending on what information the @@ -222,6 +230,13 @@ private constructor( */ fun _firstName(): JsonField = body._firstName() + /** + * Returns the raw JSON value of [flsaStatus]. + * + * Unlike [flsaStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _flsaStatus(): JsonField = body._flsaStatus() + /** * Returns the raw JSON value of [income]. * @@ -479,6 +494,23 @@ private constructor( */ fun firstName(firstName: JsonField) = apply { body.firstName(firstName) } + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + */ + fun flsaStatus(flsaStatus: FlsaStatus?) = apply { body.flsaStatus(flsaStatus) } + + /** Alias for calling [Builder.flsaStatus] with `flsaStatus.orElse(null)`. */ + fun flsaStatus(flsaStatus: Optional) = flsaStatus(flsaStatus.getOrNull()) + + /** + * Sets [Builder.flsaStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.flsaStatus] with a well-typed [FlsaStatus] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun flsaStatus(flsaStatus: JsonField) = apply { body.flsaStatus(flsaStatus) } + /** * The employee's income as reported by the provider. This may not always be annualized * income, but may be in units of bi-weekly, semi-monthly, daily, etc, depending on what @@ -817,6 +849,7 @@ private constructor( private val employmentStatus: JsonField, private val endDate: JsonField, private val firstName: JsonField, + private val flsaStatus: JsonField, private val income: JsonField, private val incomeHistory: JsonField>, private val isActive: JsonField, @@ -852,6 +885,9 @@ private constructor( @JsonProperty("first_name") @ExcludeMissing firstName: JsonField = JsonMissing.of(), + @JsonProperty("flsa_status") + @ExcludeMissing + flsaStatus: JsonField = JsonMissing.of(), @JsonProperty("income") @ExcludeMissing income: JsonField = JsonMissing.of(), @JsonProperty("income_history") @ExcludeMissing @@ -887,6 +923,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, income, incomeHistory, isActive, @@ -957,6 +994,14 @@ private constructor( */ fun firstName(): Optional = firstName.getOptional("first_name") + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. + * + * @throws FinchInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun flsaStatus(): Optional = flsaStatus.getOptional("flsa_status") + /** * The employee's income as reported by the provider. This may not always be annualized * income, but may be in units of bi-weekly, semi-monthly, daily, etc, depending on what @@ -1101,6 +1146,15 @@ private constructor( */ @JsonProperty("first_name") @ExcludeMissing fun _firstName(): JsonField = firstName + /** + * Returns the raw JSON value of [flsaStatus]. + * + * Unlike [flsaStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("flsa_status") + @ExcludeMissing + fun _flsaStatus(): JsonField = flsaStatus + /** * Returns the raw JSON value of [income]. * @@ -1214,6 +1268,7 @@ private constructor( private var employmentStatus: JsonField = JsonMissing.of() private var endDate: JsonField = JsonMissing.of() private var firstName: JsonField = JsonMissing.of() + private var flsaStatus: JsonField = JsonMissing.of() private var income: JsonField = JsonMissing.of() private var incomeHistory: JsonField>? = null private var isActive: JsonField = JsonMissing.of() @@ -1236,6 +1291,7 @@ private constructor( employmentStatus = employmentWithoutId.employmentStatus endDate = employmentWithoutId.endDate firstName = employmentWithoutId.firstName + flsaStatus = employmentWithoutId.flsaStatus income = employmentWithoutId.income incomeHistory = employmentWithoutId.incomeHistory.map { it.toMutableList() } isActive = employmentWithoutId.isActive @@ -1383,6 +1439,26 @@ private constructor( */ fun firstName(firstName: JsonField) = apply { this.firstName = firstName } + /** + * The FLSA status of the individual. Available options: `exempt`, `non_exempt`, + * `unknown`. + */ + fun flsaStatus(flsaStatus: FlsaStatus?) = flsaStatus(JsonField.ofNullable(flsaStatus)) + + /** Alias for calling [Builder.flsaStatus] with `flsaStatus.orElse(null)`. */ + fun flsaStatus(flsaStatus: Optional) = flsaStatus(flsaStatus.getOrNull()) + + /** + * Sets [Builder.flsaStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.flsaStatus] with a well-typed [FlsaStatus] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun flsaStatus(flsaStatus: JsonField) = apply { + this.flsaStatus = flsaStatus + } + /** * The employee's income as reported by the provider. This may not always be annualized * income, but may be in units of bi-weekly, semi-monthly, daily, etc, depending on what @@ -1611,6 +1687,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, income, (incomeHistory ?: JsonMissing.of()).map { it.toImmutable() }, isActive, @@ -1628,6 +1705,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmploymentWithoutId = apply { if (validated) { return@apply @@ -1640,6 +1726,7 @@ private constructor( employmentStatus().ifPresent { it.validate() } endDate() firstName() + flsaStatus().ifPresent { it.validate() } income().ifPresent { it.validate() } incomeHistory().ifPresent { it.forEach { it?.validate() } } isActive() @@ -1677,6 +1764,7 @@ private constructor( (employmentStatus.asKnown().getOrNull()?.validity() ?: 0) + (if (endDate.asKnown().isPresent) 1 else 0) + (if (firstName.asKnown().isPresent) 1 else 0) + + (flsaStatus.asKnown().getOrNull()?.validity() ?: 0) + (income.asKnown().getOrNull()?.validity() ?: 0) + (incomeHistory.asKnown().getOrNull()?.sumOf { (it?.validity() ?: 0).toInt() } ?: 0) + @@ -1703,6 +1791,7 @@ private constructor( employmentStatus == other.employmentStatus && endDate == other.endDate && firstName == other.firstName && + flsaStatus == other.flsaStatus && income == other.income && incomeHistory == other.incomeHistory && isActive == other.isActive && @@ -1726,6 +1815,7 @@ private constructor( employmentStatus, endDate, firstName, + flsaStatus, income, incomeHistory, isActive, @@ -1744,7 +1834,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "EmploymentWithoutId{classCode=$classCode, customFields=$customFields, department=$department, employment=$employment, employmentStatus=$employmentStatus, endDate=$endDate, firstName=$firstName, income=$income, incomeHistory=$incomeHistory, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, sourceId=$sourceId, startDate=$startDate, title=$title, additionalProperties=$additionalProperties}" + "EmploymentWithoutId{classCode=$classCode, customFields=$customFields, department=$department, employment=$employment, employmentStatus=$employmentStatus, endDate=$endDate, firstName=$firstName, flsaStatus=$flsaStatus, income=$income, incomeHistory=$incomeHistory, isActive=$isActive, lastName=$lastName, latestRehireDate=$latestRehireDate, location=$location, manager=$manager, middleName=$middleName, sourceId=$sourceId, startDate=$startDate, title=$title, additionalProperties=$additionalProperties}" } class CustomField @@ -1859,6 +1949,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CustomField = apply { if (validated) { return@apply @@ -2005,6 +2104,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Department = apply { if (validated) { return@apply @@ -2188,6 +2296,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Employment = apply { if (validated) { return@apply @@ -2337,6 +2454,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Subtype = apply { if (validated) { return@apply @@ -2465,6 +2592,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2643,6 +2780,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmploymentStatus = apply { if (validated) { return@apply @@ -2681,6 +2827,148 @@ private constructor( override fun toString() = value.toString() } + /** The FLSA status of the individual. Available options: `exempt`, `non_exempt`, `unknown`. */ + class FlsaStatus @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + @JvmField val EXEMPT = of("exempt") + + @JvmField val NON_EXEMPT = of("non_exempt") + + @JvmField val UNKNOWN = of("unknown") + + @JvmStatic fun of(value: String) = FlsaStatus(JsonField.of(value)) + } + + /** An enum containing [FlsaStatus]'s known values. */ + enum class Known { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + } + + /** + * An enum containing [FlsaStatus]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [FlsaStatus] 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 { + EXEMPT, + NON_EXEMPT, + UNKNOWN, + /** + * An enum member indicating that [FlsaStatus] 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) { + EXEMPT -> Value.EXEMPT + NON_EXEMPT -> Value.NON_EXEMPT + UNKNOWN -> Value.UNKNOWN + 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 FinchInvalidDataException if this class instance's value is a not a known member. + */ + fun known(): Known = + when (this) { + EXEMPT -> Known.EXEMPT + NON_EXEMPT -> Known.NON_EXEMPT + UNKNOWN -> Known.UNKNOWN + else -> throw FinchInvalidDataException("Unknown FlsaStatus: $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 FinchInvalidDataException if this class instance's value does not have the + * expected primitive type. + */ + fun asString(): String = + _value().asString().orElseThrow { FinchInvalidDataException("Value is not a String") } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): FlsaStatus = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: FinchInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FlsaStatus && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + /** The manager object representing the manager of the individual within the org. */ class Manager @JsonCreator(mode = JsonCreator.Mode.DISABLED) @@ -2780,6 +3068,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Manager = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxIndividualUpdateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxIndividualUpdateParams.kt index 276396de0..76f7b6c44 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxIndividualUpdateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxIndividualUpdateParams.kt @@ -1185,6 +1185,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): IndividualWithoutId = apply { if (validated) { return@apply @@ -1405,6 +1414,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Email = apply { if (validated) { return@apply @@ -1522,6 +1540,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1705,6 +1733,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Ethnicity = apply { if (validated) { return@apply @@ -1842,6 +1879,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Gender = apply { if (validated) { return@apply @@ -2009,6 +2055,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PhoneNumber = apply { if (validated) { return@apply @@ -2126,6 +2181,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobConfiguration.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobConfiguration.kt index 0488cedcc..6f4d90343 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobConfiguration.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobConfiguration.kt @@ -168,6 +168,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): SandboxJobConfiguration = apply { if (validated) { return@apply @@ -298,6 +306,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CompletionStatus = apply { if (validated) { return@apply @@ -416,6 +433,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobCreateParams.kt index d36ad9481..191df7850 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxJobCreateParams.kt @@ -356,6 +356,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Body = apply { if (validated) { return@apply @@ -479,6 +488,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxPaymentCreateParams.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxPaymentCreateParams.kt index 3558f8605..29c7ff3d6 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxPaymentCreateParams.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SandboxPaymentCreateParams.kt @@ -497,6 +497,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CreateSandboxPaymentRequest = apply { if (validated) { return@apply @@ -1039,6 +1048,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PayStatement = apply { if (validated) { return@apply @@ -1268,6 +1286,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Earning = apply { if (validated) { return@apply @@ -1459,6 +1487,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -1716,6 +1754,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmployeeDeduction = apply { if (validated) { return@apply @@ -1943,6 +1991,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2164,6 +2222,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmployerContribution = apply { if (validated) { return@apply @@ -2389,6 +2457,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -2548,6 +2626,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): PaymentMethod = apply { if (validated) { return@apply @@ -2772,6 +2860,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Tax = apply { if (validated) { return@apply @@ -2909,6 +3007,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match + * its expected type. + */ fun validate(): Type = apply { if (validated) { return@apply @@ -3065,6 +3173,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionNewResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionNewResponse.kt index 474bd063b..449636796 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionNewResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionNewResponse.kt @@ -167,6 +167,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): SessionNewResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionReauthenticateResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionReauthenticateResponse.kt index 98d56b708..0e3f19632 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionReauthenticateResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SessionReauthenticateResponse.kt @@ -168,6 +168,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): SessionReauthenticateResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportPerBenefitType.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportPerBenefitType.kt index d84b5fc59..b753ca199 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportPerBenefitType.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportPerBenefitType.kt @@ -161,6 +161,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): SupportPerBenefitType = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportedBenefit.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportedBenefit.kt index c438d9f23..d356fcf96 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportedBenefit.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/SupportedBenefit.kt @@ -485,6 +485,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): SupportedBenefit = apply { if (validated) { return@apply @@ -623,6 +631,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): CompanyContribution = apply { if (validated) { return@apply @@ -751,6 +768,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): EmployeeDeduction = apply { if (validated) { return@apply @@ -881,6 +907,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): HsaContributionLimit = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UnenrolledIndividualBenefitResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UnenrolledIndividualBenefitResponse.kt index fee505b45..af597b439 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UnenrolledIndividualBenefitResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UnenrolledIndividualBenefitResponse.kt @@ -131,6 +131,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): UnenrolledIndividualBenefitResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UpdateCompanyBenefitResponse.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UpdateCompanyBenefitResponse.kt index 3538acebf..4208e17cc 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UpdateCompanyBenefitResponse.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/UpdateCompanyBenefitResponse.kt @@ -161,6 +161,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): UpdateCompanyBenefitResponse = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42005.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42005.kt index 4a7396c3a..480fe3778 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42005.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42005.kt @@ -203,6 +203,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): W42005 = apply { if (validated) { return@apply @@ -537,6 +545,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -666,6 +683,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Exemption = apply { if (validated) { return@apply @@ -808,6 +835,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): FilingStatus = apply { if (validated) { return@apply @@ -958,6 +995,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42020.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42020.kt index 038aadf0f..b2f7fb35a 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42020.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/W42020.kt @@ -203,6 +203,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): W42020 = apply { if (validated) { return@apply @@ -674,6 +682,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Data = apply { if (validated) { return@apply @@ -820,6 +837,16 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing + * fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): FilingStatus = apply { if (validated) { return@apply @@ -976,6 +1003,15 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its + * expected type. + */ fun validate(): Type = apply { if (validated) { return@apply diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/WebhookEvent.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/WebhookEvent.kt index 3c1b319ac..0ba59ddc3 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/models/WebhookEvent.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/models/WebhookEvent.kt @@ -17,6 +17,7 @@ import com.tryfinch.api.core.getOrThrow import com.tryfinch.api.errors.FinchInvalidDataException import java.util.Objects import java.util.Optional +import kotlin.jvm.optionals.getOrNull @JsonDeserialize(using = WebhookEvent.Deserializer::class) @JsonSerialize(using = WebhookEvent.Serializer::class) @@ -83,6 +84,35 @@ private constructor( fun _json(): Optional = Optional.ofNullable(_json) + /** + * Maps this instance's current variant to a value of type [T] using the given [visitor]. + * + * Note that this method is _not_ forwards compatible with new variants from the API, unless + * [visitor] overrides [Visitor.unknown]. To handle variants not known to this version of the + * SDK gracefully, consider overriding [Visitor.unknown]: + * ```java + * import com.tryfinch.api.core.JsonValue; + * import java.util.Optional; + * + * Optional result = webhookEvent.accept(new WebhookEvent.Visitor>() { + * @Override + * public Optional visitAccountUpdated(AccountUpdateEvent accountUpdated) { + * return Optional.of(accountUpdated.toString()); + * } + * + * // ... + * + * @Override + * public Optional unknown(JsonValue json) { + * // Or inspect the `json`. + * return Optional.empty(); + * } + * }); + * ``` + * + * @throws FinchInvalidDataException if [Visitor.unknown] is not overridden in [visitor] and the + * current variant is unknown. + */ fun accept(visitor: Visitor): T = when { accountUpdated != null -> visitor.visitAccountUpdated(accountUpdated) @@ -98,6 +128,14 @@ private constructor( private var validated: Boolean = false + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws FinchInvalidDataException if any value type in this object doesn't match its expected + * type. + */ fun validate(): WebhookEvent = apply { if (validated) { return@apply @@ -292,18 +330,26 @@ private constructor( override fun ObjectCodec.deserialize(node: JsonNode): WebhookEvent { val json = JsonValue.fromJsonNode(node) + val eventType = json.asObject().getOrNull()?.get("event_type")?.asString()?.getOrNull() + + when (eventType) { + "account.updated" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + WebhookEvent(accountUpdated = it, _json = json) + } ?: WebhookEvent(_json = json) + } + "company.updated" -> { + return tryDeserialize(node, jacksonTypeRef())?.let { + WebhookEvent(companyUpdated = it, _json = json) + } ?: WebhookEvent(_json = json) + } + } val bestMatches = sequenceOf( - tryDeserialize(node, jacksonTypeRef())?.let { - WebhookEvent(accountUpdated = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { WebhookEvent(jobCompletion = it, _json = json) }, - tryDeserialize(node, jacksonTypeRef())?.let { - WebhookEvent(companyUpdated = it, _json = json) - }, tryDeserialize(node, jacksonTypeRef())?.let { WebhookEvent(directory = it, _json = json) }, diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccessTokenServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccessTokenServiceAsyncImpl.kt index 5558652db..7d967b1b5 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccessTokenServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccessTokenServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -96,7 +97,7 @@ class AccessTokenServiceAsyncImpl internal constructor(private val clientOptions .putAllHeaders(modifiedParams._headers()) .body(json(clientOptions.jsonMapper, modifiedParams._body())) .build() - .prepareAsync(clientOptions, modifiedParams) + .prepareAsync(clientOptions, modifiedParams, SecurityOptions.none()) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccountServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccountServiceAsyncImpl.kt index 0af47a62b..3bd8097ca 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccountServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/AccountServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -75,7 +76,11 @@ class AccountServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("disconnect") .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -105,7 +110,11 @@ class AccountServiceAsyncImpl internal constructor(private val clientOptions: Cl .baseUrl(clientOptions.baseUrl()) .addPathSegments("introspect") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/ProviderServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/ProviderServiceAsyncImpl.kt index bee420b4d..ca55f7db6 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/ProviderServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/ProviderServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -65,7 +66,11 @@ class ProviderServiceAsyncImpl internal constructor(private val clientOptions: C .baseUrl(clientOptions.baseUrl()) .addPathSegments("providers") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/RequestForwardingServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/RequestForwardingServiceAsyncImpl.kt index b004d8e63..a3dd9d02d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/RequestForwardingServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/RequestForwardingServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -68,7 +69,11 @@ internal constructor(private val clientOptions: ClientOptions) : RequestForwardi .addPathSegments("forward") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/connect/SessionServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/connect/SessionServiceAsyncImpl.kt index 90219852e..d39f48d4d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/connect/SessionServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/connect/SessionServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.connect import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -75,7 +76,11 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("connect", "sessions") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -106,7 +111,11 @@ class SessionServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("connect", "sessions", "reauthenticate") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/BenefitServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/BenefitServiceAsyncImpl.kt index a19b40949..9cf3cc6b2 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/BenefitServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/BenefitServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -120,7 +121,11 @@ class BenefitServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("employer", "benefits") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -153,7 +158,11 @@ class BenefitServiceAsyncImpl internal constructor(private val clientOptions: Cl .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", params._pathParam(0)) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -187,7 +196,11 @@ class BenefitServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("employer", "benefits", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -217,7 +230,11 @@ class BenefitServiceAsyncImpl internal constructor(private val clientOptions: Cl .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -255,7 +272,11 @@ class BenefitServiceAsyncImpl internal constructor(private val clientOptions: Cl .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", "meta") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/CompanyServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/CompanyServiceAsyncImpl.kt index 375083001..625ab9155 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/CompanyServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/CompanyServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -79,7 +80,11 @@ class CompanyServiceAsyncImpl internal constructor(private val clientOptions: Cl .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "company") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DirectoryServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DirectoryServiceAsyncImpl.kt index 096c5d26f..47977c620 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DirectoryServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DirectoryServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -75,7 +76,11 @@ class DirectoryServiceAsyncImpl internal constructor(private val clientOptions: .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "directory") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -114,7 +119,11 @@ class DirectoryServiceAsyncImpl internal constructor(private val clientOptions: .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "directory") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DocumentServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DocumentServiceAsyncImpl.kt index f23f13a8a..e81824fa9 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DocumentServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/DocumentServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -75,7 +76,11 @@ class DocumentServiceAsyncImpl internal constructor(private val clientOptions: C .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "documents") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -108,7 +113,11 @@ class DocumentServiceAsyncImpl internal constructor(private val clientOptions: C .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "documents", params._pathParam(0)) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/EmploymentServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/EmploymentServiceAsyncImpl.kt index 969a5223a..0ed3920bc 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/EmploymentServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/EmploymentServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -67,7 +68,11 @@ class EmploymentServiceAsyncImpl internal constructor(private val clientOptions: .addPathSegments("employer", "employment") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/IndividualServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/IndividualServiceAsyncImpl.kt index a81e28e52..e17a2375a 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/IndividualServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/IndividualServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -67,7 +68,11 @@ class IndividualServiceAsyncImpl internal constructor(private val clientOptions: .addPathSegments("employer", "individual") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PayStatementServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PayStatementServiceAsyncImpl.kt index 48b59148d..915e1628a 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PayStatementServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PayStatementServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -67,7 +68,11 @@ class PayStatementServiceAsyncImpl internal constructor(private val clientOption .addPathSegments("employer", "pay-statement") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PaymentServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PaymentServiceAsyncImpl.kt index 555b86d39..c0baee8c9 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PaymentServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/PaymentServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -65,7 +66,11 @@ class PaymentServiceAsyncImpl internal constructor(private val clientOptions: Cl .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "payment") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/benefits/IndividualServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/benefits/IndividualServiceAsyncImpl.kt index f2a30337d..a53af4c3d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/benefits/IndividualServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/benefits/IndividualServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris.benefits import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -89,7 +90,11 @@ class IndividualServiceAsyncImpl internal constructor(private val clientOptions: .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", params._pathParam(0), "enrolled") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -122,7 +127,11 @@ class IndividualServiceAsyncImpl internal constructor(private val clientOptions: .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", params._pathParam(0), "individuals") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -164,7 +173,11 @@ class IndividualServiceAsyncImpl internal constructor(private val clientOptions: .addPathSegments("employer", "benefits", params._pathParam(0), "individuals") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/PayStatementItemServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/PayStatementItemServiceAsyncImpl.kt index 59a4ca7b8..896b0943f 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/PayStatementItemServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/PayStatementItemServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris.company import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -79,7 +80,11 @@ internal constructor(private val clientOptions: ClientOptions) : PayStatementIte .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-statement-item") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/payStatementItem/RuleServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/payStatementItem/RuleServiceAsyncImpl.kt index 8dd4d38fd..d3a72353f 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/payStatementItem/RuleServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/hris/company/payStatementItem/RuleServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.hris.company.payStatementItem import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -96,7 +97,11 @@ class RuleServiceAsyncImpl internal constructor(private val clientOptions: Clien .addPathSegments("employer", "pay-statement-item", "rule") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -130,7 +135,11 @@ class RuleServiceAsyncImpl internal constructor(private val clientOptions: Clien .addPathSegments("employer", "pay-statement-item", "rule", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -160,7 +169,11 @@ class RuleServiceAsyncImpl internal constructor(private val clientOptions: Clien .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-statement-item", "rule") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -202,7 +215,11 @@ class RuleServiceAsyncImpl internal constructor(private val clientOptions: Clien .addPathSegments("employer", "pay-statement-item", "rule", params._pathParam(0)) .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsync.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsync.kt index 732dff37a..93a7f533d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsync.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsync.kt @@ -43,23 +43,41 @@ interface AutomatedServiceAsync { * This endpoint is available for *Scale* tier customers as an add-on. To request access to this * endpoint, please contact your Finch account manager. */ - fun create(): CompletableFuture = - create(JobAutomatedCreateParams.none()) + fun create(params: JobAutomatedCreateParams): CompletableFuture = + create(params, RequestOptions.none()) /** @see create */ fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none(), + params: JobAutomatedCreateParams, requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture /** @see create */ fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none() - ): CompletableFuture = create(params, RequestOptions.none()) + body: JobAutomatedCreateParams.Body, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + create(JobAutomatedCreateParams.builder().body(body).build(), requestOptions) + + /** @see create */ + fun create(body: JobAutomatedCreateParams.Body): CompletableFuture = + create(body, RequestOptions.none()) + + /** @see create */ + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture = + create( + JobAutomatedCreateParams.Body.ofW4FormEmployeeSync(w4FormEmployeeSync), + requestOptions, + ) /** @see create */ - fun create(requestOptions: RequestOptions): CompletableFuture = - create(JobAutomatedCreateParams.none(), requestOptions) + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync + ): CompletableFuture = + create(w4FormEmployeeSync, RequestOptions.none()) /** Get an automated job by `job_id`. */ fun retrieve(jobId: String): CompletableFuture = @@ -136,26 +154,45 @@ interface AutomatedServiceAsync { * Returns a raw HTTP response for `post /jobs/automated`, but is otherwise the same as * [AutomatedServiceAsync.create]. */ - fun create(): CompletableFuture> = - create(JobAutomatedCreateParams.none()) + fun create( + params: JobAutomatedCreateParams + ): CompletableFuture> = + create(params, RequestOptions.none()) /** @see create */ fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none(), + params: JobAutomatedCreateParams, requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> /** @see create */ fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none() + body: JobAutomatedCreateParams.Body, + requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture> = - create(params, RequestOptions.none()) + create(JobAutomatedCreateParams.builder().body(body).build(), requestOptions) /** @see create */ fun create( - requestOptions: RequestOptions + body: JobAutomatedCreateParams.Body + ): CompletableFuture> = + create(body, RequestOptions.none()) + + /** @see create */ + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + create( + JobAutomatedCreateParams.Body.ofW4FormEmployeeSync(w4FormEmployeeSync), + requestOptions, + ) + + /** @see create */ + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync ): CompletableFuture> = - create(JobAutomatedCreateParams.none(), requestOptions) + create(w4FormEmployeeSync, RequestOptions.none()) /** * Returns a raw HTTP response for `get /jobs/automated/{job_id}`, but is otherwise the same diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncImpl.kt index 7759f18ac..ff2a94d2c 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.jobs import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -84,9 +85,13 @@ class AutomatedServiceAsyncImpl internal constructor(private val clientOptions: .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "automated") - .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -119,7 +124,11 @@ class AutomatedServiceAsyncImpl internal constructor(private val clientOptions: .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "automated", params._pathParam(0)) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -149,7 +158,11 @@ class AutomatedServiceAsyncImpl internal constructor(private val clientOptions: .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "automated") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/ManualServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/ManualServiceAsyncImpl.kt index c570f4208..2f67f27f4 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/ManualServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/jobs/ManualServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.jobs import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -69,7 +70,11 @@ class ManualServiceAsyncImpl internal constructor(private val clientOptions: Cli .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "manual", params._pathParam(0)) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/payroll/PayGroupServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/payroll/PayGroupServiceAsyncImpl.kt index 88880d4e3..8582ef31d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/payroll/PayGroupServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/payroll/PayGroupServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.payroll import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -79,7 +80,11 @@ class PayGroupServiceAsyncImpl internal constructor(private val clientOptions: C .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-groups", params._pathParam(0)) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -109,7 +114,11 @@ class PayGroupServiceAsyncImpl internal constructor(private val clientOptions: C .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-groups") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/CompanyServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/CompanyServiceAsyncImpl.kt index 847d2ecf2..e46752776 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/CompanyServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/CompanyServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -66,7 +67,11 @@ class CompanyServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("sandbox", "company") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/ConnectionServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/ConnectionServiceAsyncImpl.kt index 95e642fec..973350a90 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/ConnectionServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/ConnectionServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -78,7 +79,11 @@ class ConnectionServiceAsyncImpl internal constructor(private val clientOptions: .addPathSegments("sandbox", "connections") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsync.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsync.kt index 2d566ef2c..49c92fb0e 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsync.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsync.kt @@ -39,6 +39,18 @@ interface DirectoryServiceAsync { params: SandboxDirectoryCreateParams = SandboxDirectoryCreateParams.none() ): CompletableFuture> = create(params, RequestOptions.none()) + /** @see create */ + fun create( + body: List, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> = + create(SandboxDirectoryCreateParams.builder().body(body).build(), requestOptions) + + /** @see create */ + fun create( + body: List + ): CompletableFuture> = create(body, RequestOptions.none()) + /** @see create */ fun create(requestOptions: RequestOptions): CompletableFuture> = create(SandboxDirectoryCreateParams.none(), requestOptions) @@ -76,6 +88,19 @@ interface DirectoryServiceAsync { ): CompletableFuture>> = create(params, RequestOptions.none()) + /** @see create */ + fun create( + body: List, + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture>> = + create(SandboxDirectoryCreateParams.builder().body(body).build(), requestOptions) + + /** @see create */ + fun create( + body: List + ): CompletableFuture>> = + create(body, RequestOptions.none()) + /** @see create */ fun create( requestOptions: RequestOptions diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncImpl.kt index ca2360a0e..3b6b3ec1e 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -66,7 +67,11 @@ class DirectoryServiceAsyncImpl internal constructor(private val clientOptions: .addPathSegments("sandbox", "directory") .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncImpl.kt index fd15ae5a7..3e97a0c1d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -71,7 +72,11 @@ class EmploymentServiceAsyncImpl internal constructor(private val clientOptions: .addPathSegments("sandbox", "employment", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/IndividualServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/IndividualServiceAsyncImpl.kt index 923d4583b..5e06bc51c 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/IndividualServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/IndividualServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -71,7 +72,11 @@ class IndividualServiceAsyncImpl internal constructor(private val clientOptions: .addPathSegments("sandbox", "individual", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/JobServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/JobServiceAsyncImpl.kt index 58779d34a..4bee36ba1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/JobServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/JobServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -80,7 +81,11 @@ class JobServiceAsyncImpl internal constructor(private val clientOptions: Client .addPathSegments("sandbox", "jobs") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/PaymentServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/PaymentServiceAsyncImpl.kt index 50f618dc3..dbd8033c0 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/PaymentServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/PaymentServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -66,7 +67,11 @@ class PaymentServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("sandbox", "payment") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/connections/AccountServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/connections/AccountServiceAsyncImpl.kt index a8228caa8..1bbe630ff 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/connections/AccountServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/connections/AccountServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox.connections import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -75,7 +76,11 @@ class AccountServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("sandbox", "connections", "accounts") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -106,7 +111,11 @@ class AccountServiceAsyncImpl internal constructor(private val clientOptions: Cl .addPathSegments("sandbox", "connections", "accounts") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/jobs/ConfigurationServiceAsyncImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/jobs/ConfigurationServiceAsyncImpl.kt index 66aa1b5d2..f1939fb7a 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/jobs/ConfigurationServiceAsyncImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/async/sandbox/jobs/ConfigurationServiceAsyncImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.async.sandbox.jobs import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -73,7 +74,11 @@ class ConfigurationServiceAsyncImpl internal constructor(private val clientOptio .baseUrl(clientOptions.baseUrl()) .addPathSegments("sandbox", "jobs", "configuration") .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } @@ -104,7 +109,11 @@ class ConfigurationServiceAsyncImpl internal constructor(private val clientOptio .addPathSegments("sandbox", "jobs", "configuration") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepareAsync(clientOptions, params) + .prepareAsync( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccessTokenServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccessTokenServiceImpl.kt index 00b0eb956..50ab01eda 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccessTokenServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccessTokenServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -95,7 +96,7 @@ class AccessTokenServiceImpl internal constructor(private val clientOptions: Cli .putAllHeaders(modifiedParams._headers()) .body(json(clientOptions.jsonMapper, modifiedParams._body())) .build() - .prepare(clientOptions, modifiedParams) + .prepare(clientOptions, modifiedParams, SecurityOptions.none()) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccountServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccountServiceImpl.kt index a210238b6..966aaa070 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccountServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/AccountServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -74,7 +75,11 @@ class AccountServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("disconnect") .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -101,7 +106,11 @@ class AccountServiceImpl internal constructor(private val clientOptions: ClientO .baseUrl(clientOptions.baseUrl()) .addPathSegments("introspect") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/ProviderServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/ProviderServiceImpl.kt index 28b0539e0..f36645d7f 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/ProviderServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/ProviderServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -64,7 +65,11 @@ class ProviderServiceImpl internal constructor(private val clientOptions: Client .baseUrl(clientOptions.baseUrl()) .addPathSegments("providers") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/RequestForwardingServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/RequestForwardingServiceImpl.kt index c1be768bb..814984397 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/RequestForwardingServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/RequestForwardingServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -65,7 +66,11 @@ class RequestForwardingServiceImpl internal constructor(private val clientOption .addPathSegments("forward") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/connect/SessionServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/connect/SessionServiceImpl.kt index 13642f425..afc9ad975 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/connect/SessionServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/connect/SessionServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.connect import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -74,7 +75,11 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("connect", "sessions") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -102,7 +107,11 @@ class SessionServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("connect", "sessions", "reauthenticate") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/BenefitServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/BenefitServiceImpl.kt index dda2c59ce..a4f4e4d79 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/BenefitServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/BenefitServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -117,7 +118,11 @@ class BenefitServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("employer", "benefits") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -147,7 +152,11 @@ class BenefitServiceImpl internal constructor(private val clientOptions: ClientO .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", params._pathParam(0)) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -178,7 +187,11 @@ class BenefitServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("employer", "benefits", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -205,7 +218,11 @@ class BenefitServiceImpl internal constructor(private val clientOptions: ClientO .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -239,7 +256,11 @@ class BenefitServiceImpl internal constructor(private val clientOptions: ClientO .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", "meta") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/CompanyServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/CompanyServiceImpl.kt index 3ae6dd45b..5ea58bc6d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/CompanyServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/CompanyServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -77,7 +78,11 @@ class CompanyServiceImpl internal constructor(private val clientOptions: ClientO .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "company") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DirectoryServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DirectoryServiceImpl.kt index d22054c3e..243b719cc 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DirectoryServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DirectoryServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -74,7 +75,11 @@ class DirectoryServiceImpl internal constructor(private val clientOptions: Clien .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "directory") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -109,7 +114,11 @@ class DirectoryServiceImpl internal constructor(private val clientOptions: Clien .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "directory") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DocumentServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DocumentServiceImpl.kt index 97a65e748..424340725 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DocumentServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/DocumentServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -74,7 +75,11 @@ class DocumentServiceImpl internal constructor(private val clientOptions: Client .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "documents") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -104,7 +109,11 @@ class DocumentServiceImpl internal constructor(private val clientOptions: Client .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "documents", params._pathParam(0)) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/EmploymentServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/EmploymentServiceImpl.kt index a8efa09d0..10d029bb1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/EmploymentServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/EmploymentServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -66,7 +67,11 @@ class EmploymentServiceImpl internal constructor(private val clientOptions: Clie .addPathSegments("employer", "employment") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/IndividualServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/IndividualServiceImpl.kt index 362faadae..75887cf25 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/IndividualServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/IndividualServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -66,7 +67,11 @@ class IndividualServiceImpl internal constructor(private val clientOptions: Clie .addPathSegments("employer", "individual") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PayStatementServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PayStatementServiceImpl.kt index 645b00c52..c0fd0ed18 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PayStatementServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PayStatementServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -66,7 +67,11 @@ class PayStatementServiceImpl internal constructor(private val clientOptions: Cl .addPathSegments("employer", "pay-statement") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PaymentServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PaymentServiceImpl.kt index 3a8f892ba..ef79f8596 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PaymentServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/PaymentServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -64,7 +65,11 @@ class PaymentServiceImpl internal constructor(private val clientOptions: ClientO .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "payment") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/benefits/IndividualServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/benefits/IndividualServiceImpl.kt index 7109b6e67..467c2949c 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/benefits/IndividualServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/benefits/IndividualServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris.benefits import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -88,7 +89,11 @@ class IndividualServiceImpl internal constructor(private val clientOptions: Clie .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", params._pathParam(0), "enrolled") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -118,7 +123,11 @@ class IndividualServiceImpl internal constructor(private val clientOptions: Clie .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "benefits", params._pathParam(0), "individuals") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -156,7 +165,11 @@ class IndividualServiceImpl internal constructor(private val clientOptions: Clie .addPathSegments("employer", "benefits", params._pathParam(0), "individuals") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/PayStatementItemServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/PayStatementItemServiceImpl.kt index 8626076cf..5cc9916b3 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/PayStatementItemServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/PayStatementItemServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris.company import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -76,7 +77,11 @@ class PayStatementItemServiceImpl internal constructor(private val clientOptions .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-statement-item") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/payStatementItem/RuleServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/payStatementItem/RuleServiceImpl.kt index 030e53cb5..5c9d084ae 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/payStatementItem/RuleServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/hris/company/payStatementItem/RuleServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.hris.company.payStatementItem import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -94,7 +95,11 @@ class RuleServiceImpl internal constructor(private val clientOptions: ClientOpti .addPathSegments("employer", "pay-statement-item", "rule") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -125,7 +130,11 @@ class RuleServiceImpl internal constructor(private val clientOptions: ClientOpti .addPathSegments("employer", "pay-statement-item", "rule", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -152,7 +161,11 @@ class RuleServiceImpl internal constructor(private val clientOptions: ClientOpti .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-statement-item", "rule") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -190,7 +203,11 @@ class RuleServiceImpl internal constructor(private val clientOptions: ClientOpti .addPathSegments("employer", "pay-statement-item", "rule", params._pathParam(0)) .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedService.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedService.kt index a9cef18d8..fe3a3081c 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedService.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedService.kt @@ -43,22 +43,40 @@ interface AutomatedService { * This endpoint is available for *Scale* tier customers as an add-on. To request access to this * endpoint, please contact your Finch account manager. */ - fun create(): AutomatedCreateResponse = create(JobAutomatedCreateParams.none()) + fun create(params: JobAutomatedCreateParams): AutomatedCreateResponse = + create(params, RequestOptions.none()) /** @see create */ fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none(), + params: JobAutomatedCreateParams, requestOptions: RequestOptions = RequestOptions.none(), ): AutomatedCreateResponse /** @see create */ fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none() - ): AutomatedCreateResponse = create(params, RequestOptions.none()) + body: JobAutomatedCreateParams.Body, + requestOptions: RequestOptions = RequestOptions.none(), + ): AutomatedCreateResponse = + create(JobAutomatedCreateParams.builder().body(body).build(), requestOptions) + + /** @see create */ + fun create(body: JobAutomatedCreateParams.Body): AutomatedCreateResponse = + create(body, RequestOptions.none()) /** @see create */ - fun create(requestOptions: RequestOptions): AutomatedCreateResponse = - create(JobAutomatedCreateParams.none(), requestOptions) + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync, + requestOptions: RequestOptions = RequestOptions.none(), + ): AutomatedCreateResponse = + create( + JobAutomatedCreateParams.Body.ofW4FormEmployeeSync(w4FormEmployeeSync), + requestOptions, + ) + + /** @see create */ + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync + ): AutomatedCreateResponse = create(w4FormEmployeeSync, RequestOptions.none()) /** Get an automated job by `job_id`. */ fun retrieve(jobId: String): AutomatedAsyncJob = @@ -128,26 +146,46 @@ interface AutomatedService { * [AutomatedService.create]. */ @MustBeClosed - fun create(): HttpResponseFor = - create(JobAutomatedCreateParams.none()) + fun create(params: JobAutomatedCreateParams): HttpResponseFor = + create(params, RequestOptions.none()) /** @see create */ @MustBeClosed fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none(), + params: JobAutomatedCreateParams, requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor /** @see create */ @MustBeClosed fun create( - params: JobAutomatedCreateParams = JobAutomatedCreateParams.none() - ): HttpResponseFor = create(params, RequestOptions.none()) + body: JobAutomatedCreateParams.Body, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(JobAutomatedCreateParams.builder().body(body).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create(body: JobAutomatedCreateParams.Body): HttpResponseFor = + create(body, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create( + JobAutomatedCreateParams.Body.ofW4FormEmployeeSync(w4FormEmployeeSync), + requestOptions, + ) /** @see create */ @MustBeClosed - fun create(requestOptions: RequestOptions): HttpResponseFor = - create(JobAutomatedCreateParams.none(), requestOptions) + fun create( + w4FormEmployeeSync: JobAutomatedCreateParams.Body.W4FormEmployeeSync + ): HttpResponseFor = + create(w4FormEmployeeSync, RequestOptions.none()) /** * Returns a raw HTTP response for `get /jobs/automated/{job_id}`, but is otherwise the same diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceImpl.kt index b92a01c7b..70669ec2b 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.jobs import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -83,9 +84,13 @@ class AutomatedServiceImpl internal constructor(private val clientOptions: Clien .method(HttpMethod.POST) .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "automated") - .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } + .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -115,7 +120,11 @@ class AutomatedServiceImpl internal constructor(private val clientOptions: Clien .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "automated", params._pathParam(0)) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -142,7 +151,11 @@ class AutomatedServiceImpl internal constructor(private val clientOptions: Clien .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "automated") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/ManualServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/ManualServiceImpl.kt index 6f809d2ef..2610eb459 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/ManualServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/jobs/ManualServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.jobs import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -68,7 +69,11 @@ class ManualServiceImpl internal constructor(private val clientOptions: ClientOp .baseUrl(clientOptions.baseUrl()) .addPathSegments("jobs", "manual", params._pathParam(0)) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/payroll/PayGroupServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/payroll/PayGroupServiceImpl.kt index 67dd133e7..03deb37ff 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/payroll/PayGroupServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/payroll/PayGroupServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.payroll import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -78,7 +79,11 @@ class PayGroupServiceImpl internal constructor(private val clientOptions: Client .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-groups", params._pathParam(0)) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -105,7 +110,11 @@ class PayGroupServiceImpl internal constructor(private val clientOptions: Client .baseUrl(clientOptions.baseUrl()) .addPathSegments("employer", "pay-groups") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/CompanyServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/CompanyServiceImpl.kt index 73fedc5bf..0f1d0def1 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/CompanyServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/CompanyServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -65,7 +66,11 @@ class CompanyServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("sandbox", "company") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/ConnectionServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/ConnectionServiceImpl.kt index d7c20374d..98c5e7714 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/ConnectionServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/ConnectionServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -77,7 +78,11 @@ class ConnectionServiceImpl internal constructor(private val clientOptions: Clie .addPathSegments("sandbox", "connections") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryService.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryService.kt index 2b9fda7d9..e4e86616a 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryService.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryService.kt @@ -38,6 +38,18 @@ interface DirectoryService { params: SandboxDirectoryCreateParams = SandboxDirectoryCreateParams.none() ): List = create(params, RequestOptions.none()) + /** @see create */ + fun create( + body: List, + requestOptions: RequestOptions = RequestOptions.none(), + ): List = + create(SandboxDirectoryCreateParams.builder().body(body).build(), requestOptions) + + /** @see create */ + fun create( + body: List + ): List = create(body, RequestOptions.none()) + /** @see create */ fun create(requestOptions: RequestOptions): List = create(SandboxDirectoryCreateParams.none(), requestOptions) @@ -73,6 +85,20 @@ interface DirectoryService { params: SandboxDirectoryCreateParams = SandboxDirectoryCreateParams.none() ): HttpResponseFor> = create(params, RequestOptions.none()) + /** @see create */ + @MustBeClosed + fun create( + body: List, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> = + create(SandboxDirectoryCreateParams.builder().body(body).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create( + body: List + ): HttpResponseFor> = create(body, RequestOptions.none()) + /** @see create */ @MustBeClosed fun create(requestOptions: RequestOptions): HttpResponseFor> = diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceImpl.kt index b71b5e155..d536be678 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -65,7 +66,11 @@ class DirectoryServiceImpl internal constructor(private val clientOptions: Clien .addPathSegments("sandbox", "directory") .apply { params._body().ifPresent { body(json(clientOptions.jsonMapper, it)) } } .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceImpl.kt index 72485f2b3..98cc6373a 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -70,7 +71,11 @@ class EmploymentServiceImpl internal constructor(private val clientOptions: Clie .addPathSegments("sandbox", "employment", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/IndividualServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/IndividualServiceImpl.kt index 877e49232..4362a6c3b 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/IndividualServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/IndividualServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.checkRequired import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler @@ -70,7 +71,11 @@ class IndividualServiceImpl internal constructor(private val clientOptions: Clie .addPathSegments("sandbox", "individual", params._pathParam(0)) .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/JobServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/JobServiceImpl.kt index e2d7efcd9..b92563032 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/JobServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/JobServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -78,7 +79,11 @@ class JobServiceImpl internal constructor(private val clientOptions: ClientOptio .addPathSegments("sandbox", "jobs") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/PaymentServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/PaymentServiceImpl.kt index f3df9473b..276ff208d 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/PaymentServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/PaymentServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -65,7 +66,11 @@ class PaymentServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("sandbox", "payment") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/connections/AccountServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/connections/AccountServiceImpl.kt index 5adfb73e8..6e633e187 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/connections/AccountServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/connections/AccountServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox.connections import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -74,7 +75,11 @@ class AccountServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("sandbox", "connections", "accounts") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().basicAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -102,7 +107,11 @@ class AccountServiceImpl internal constructor(private val clientOptions: ClientO .addPathSegments("sandbox", "connections", "accounts") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/jobs/ConfigurationServiceImpl.kt b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/jobs/ConfigurationServiceImpl.kt index 45e09a3dc..8afdfb574 100644 --- a/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/jobs/ConfigurationServiceImpl.kt +++ b/finch-java-core/src/main/kotlin/com/tryfinch/api/services/blocking/sandbox/jobs/ConfigurationServiceImpl.kt @@ -4,6 +4,7 @@ package com.tryfinch.api.services.blocking.sandbox.jobs import com.tryfinch.api.core.ClientOptions import com.tryfinch.api.core.RequestOptions +import com.tryfinch.api.core.SecurityOptions import com.tryfinch.api.core.handlers.errorBodyHandler import com.tryfinch.api.core.handlers.errorHandler import com.tryfinch.api.core.handlers.jsonHandler @@ -72,7 +73,11 @@ class ConfigurationServiceImpl internal constructor(private val clientOptions: C .baseUrl(clientOptions.baseUrl()) .addPathSegments("sandbox", "jobs", "configuration") .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { @@ -100,7 +105,11 @@ class ConfigurationServiceImpl internal constructor(private val clientOptions: C .addPathSegments("sandbox", "jobs", "configuration") .body(json(clientOptions.jsonMapper, params._body())) .build() - .prepare(clientOptions, params) + .prepare( + clientOptions, + params, + SecurityOptions.builder().bearerAuth(true).build(), + ) val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return errorHandler.handle(response).parseable { diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/TestServerExtension.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/TestServerExtension.kt index 5e740846a..3c60724ca 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/TestServerExtension.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/TestServerExtension.kt @@ -15,25 +15,12 @@ class TestServerExtension : BeforeAllCallback, ExecutionCondition { } catch (e: Exception) { throw RuntimeException( """ - The test suite will not run without a mock Prism server running against your OpenAPI spec. + The test suite will not run without a mock server running against your OpenAPI spec. You can set the environment variable `SKIP_MOCK_TESTS` to `true` to skip running any tests that require the mock server. - To fix: - - 1. Install Prism (requires Node 16+): - - With npm: - $ npm install -g @stoplight/prism-cli - - With yarn: - $ yarn global add @stoplight/prism-cli - - 2. Run the mock server - - To run the server, pass in the path of your OpenAPI spec to the prism command: - $ prism mock path/to/your.openapi.yml + To fix run `./scripts/mock` in a separate terminal. """ .trimIndent(), e, diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/core/ClientOptionsTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/ClientOptionsTest.kt index 893b3b428..62df61358 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/core/ClientOptionsTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/ClientOptionsTest.kt @@ -16,6 +16,20 @@ internal class ClientOptionsTest { private val httpClient = mock() + @Test + fun putHeader_canOverwriteDefaultHeader() { + val clientOptions = + ClientOptions.builder() + .httpClient(httpClient) + .putHeader("User-Agent", "My User Agent") + .accessToken("My Access Token") + .clientId("4ab15e51-11ad-49f4-acae-f343b7794375") + .clientSecret("My Client Secret") + .build() + + assertThat(clientOptions.headers.values("User-Agent")).containsExactly("My User Agent") + } + @Test fun toBuilder_whenOriginalClientOptionsGarbageCollected_doesNotCloseOriginalClient() { var clientOptions = diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/HttpRequestBodiesTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/HttpRequestBodiesTest.kt new file mode 100644 index 000000000..1f55aa5e4 --- /dev/null +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/HttpRequestBodiesTest.kt @@ -0,0 +1,739 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.tryfinch.api.core.http + +import com.tryfinch.api.core.MultipartField +import com.tryfinch.api.core.jsonMapper +import java.io.ByteArrayOutputStream +import java.io.InputStream +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class HttpRequestBodiesTest { + + @Test + fun multipartFormData_serializesFieldWithFilename() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "file" to + MultipartField.builder() + .value("hello") + .filename("hello.txt") + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(output.size().toLong()).isEqualTo(body.contentLength()) + val boundary = body.contentType()!!.substringAfter("multipart/form-data; boundary=") + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="file"; filename="hello.txt" + |Content-Type: text/plain + | + |hello + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesFieldWithoutFilename() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "field" to + MultipartField.builder() + .value("value") + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(output.size().toLong()).isEqualTo(body.contentLength()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="field" + |Content-Type: text/plain + | + |value + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesInputStream() { + // Use `.buffered()` to get a non-ByteArrayInputStream, which hits the non-repeatable code + // path. + val inputStream = "stream content".byteInputStream().buffered() + val body = + multipartFormData( + jsonMapper(), + mapOf( + "data" to + MultipartField.builder() + .value(inputStream) + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isFalse() + assertThat(body.contentLength()).isEqualTo(-1L) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="data" + |Content-Type: application/octet-stream + | + |stream content + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesByteArray() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "binary" to + MultipartField.builder() + .value("abc".toByteArray()) + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="binary" + |Content-Type: application/octet-stream + | + |abc + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesBooleanValue() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "flag" to + MultipartField.builder() + .value(true) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="flag" + |Content-Type: text/plain + | + |true + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesNumberValue() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "count" to + MultipartField.builder().value(42).contentType("text/plain").build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="count" + |Content-Type: text/plain + | + |42 + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesNullValueAsNoParts() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "present" to + MultipartField.builder() + .value("yes") + .contentType("text/plain") + .build(), + "absent" to + MultipartField.builder() + .value(null as String?) + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="present" + |Content-Type: text/plain + | + |yes + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesArray() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "items" to + MultipartField.builder>() + .value(listOf("alpha", "beta", "gamma")) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="items[]" + |Content-Type: text/plain + | + |alpha + |--$boundary + |Content-Disposition: form-data; name="items[]" + |Content-Type: text/plain + | + |beta + |--$boundary + |Content-Disposition: form-data; name="items[]" + |Content-Type: text/plain + | + |gamma + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesObjectAsNestedParts() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "meta" to + MultipartField.builder>() + .value(mapOf("key1" to "val1", "key2" to "val2")) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="meta[key1]" + |Content-Type: text/plain + | + |val1 + |--$boundary + |Content-Disposition: form-data; name="meta[key2]" + |Content-Type: text/plain + | + |val2 + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesMultipleFields() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "name" to + MultipartField.builder() + .value("Alice") + .contentType("text/plain") + .build(), + "age" to + MultipartField.builder().value(30).contentType("text/plain").build(), + "file" to + MultipartField.builder() + .value("file contents") + .filename("doc.txt") + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="name" + |Content-Type: text/plain + | + |Alice + |--$boundary + |Content-Disposition: form-data; name="age" + |Content-Type: text/plain + | + |30 + |--$boundary + |Content-Disposition: form-data; name="file"; filename="doc.txt" + |Content-Type: text/plain + | + |file contents + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_quotesSpecialCharactersInNameAndFilename() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "field\nname" to + MultipartField.builder() + .value("value") + .filename("file\r\"name.txt") + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="field%0Aname"; filename="file%0D%22name.txt" + |Content-Type: text/plain + | + |value + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_writeIsRepeatable() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "field" to + MultipartField.builder() + .value("repeatable") + .contentType("text/plain") + .build() + ), + ) + + val output1 = ByteArrayOutputStream() + body.writeTo(output1) + val output2 = ByteArrayOutputStream() + body.writeTo(output2) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output1.size().toLong()) + val boundary = boundary(body) + val expected = + """ + |--$boundary + |Content-Disposition: form-data; name="field" + |Content-Type: text/plain + | + |repeatable + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + assertThat(output1.toString("UTF-8")).isEqualTo(expected) + assertThat(output2.toString("UTF-8")).isEqualTo(expected) + } + + @Test + fun multipartFormData_serializesByteArrayInputStream() { + // ByteArrayInputStream is specifically handled as repeatable with known content length. + val inputStream = "byte array stream".byteInputStream() + val body = + multipartFormData( + jsonMapper(), + mapOf( + "data" to + MultipartField.builder() + .value(inputStream) + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="data" + |Content-Type: application/octet-stream + | + |byte array stream + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesInputStreamWithFilename() { + // Use `.buffered()` to get a non-ByteArrayInputStream, which hits the non-repeatable code + // path. + val inputStream = "file data".byteInputStream().buffered() + val body = + multipartFormData( + jsonMapper(), + mapOf( + "upload" to + MultipartField.builder() + .value(inputStream) + .filename("upload.bin") + .contentType("application/octet-stream") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isFalse() + assertThat(body.contentLength()).isEqualTo(-1L) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="upload"; filename="upload.bin" + |Content-Type: application/octet-stream + | + |file data + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesNestedArrayInObject() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "data" to + MultipartField.builder>>() + .value(mapOf("tags" to listOf("a", "b"))) + .contentType("text/plain") + .build() + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="data[tags][]" + |Content-Type: text/plain + | + |a + |--$boundary + |Content-Disposition: form-data; name="data[tags][]" + |Content-Type: text/plain + | + |b + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_contentLengthIsUnknownWhenInputStreamPresent() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "text" to + MultipartField.builder() + .value("hello") + .contentType("text/plain") + .build(), + "stream" to + MultipartField.builder() + // Use `.buffered()` to get a non-ByteArrayInputStream, which hits the + // non-repeatable code path. + .value("data".byteInputStream().buffered()) + .contentType("application/octet-stream") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isFalse() + assertThat(body.contentLength()).isEqualTo(-1L) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="text" + |Content-Type: text/plain + | + |hello + |--$boundary + |Content-Disposition: form-data; name="stream" + |Content-Type: application/octet-stream + | + |data + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesEmptyArray() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "required" to + MultipartField.builder() + .value("present") + .contentType("text/plain") + .build(), + "items" to + MultipartField.builder>() + .value(emptyList()) + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="required" + |Content-Type: text/plain + | + |present + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + @Test + fun multipartFormData_serializesEmptyObject() { + val body = + multipartFormData( + jsonMapper(), + mapOf( + "required" to + MultipartField.builder() + .value("present") + .contentType("text/plain") + .build(), + "meta" to + MultipartField.builder>() + .value(emptyMap()) + .contentType("text/plain") + .build(), + ), + ) + + val output = ByteArrayOutputStream() + body.writeTo(output) + + assertThat(body.repeatable()).isTrue() + assertThat(body.contentLength()).isEqualTo(output.size().toLong()) + val boundary = boundary(body) + assertThat(output.toString("UTF-8")) + .isEqualTo( + """ + |--$boundary + |Content-Disposition: form-data; name="required" + |Content-Type: text/plain + | + |present + |--$boundary-- + | + """ + .trimMargin() + .replace("\n", "\r\n") + ) + } + + private fun boundary(body: HttpRequestBody): String = + body.contentType()!!.substringAfter("multipart/form-data; boundary=") +} diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/LoggingHttpClientTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/LoggingHttpClientTest.kt new file mode 100644 index 000000000..57125ca04 --- /dev/null +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/LoggingHttpClientTest.kt @@ -0,0 +1,1000 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.tryfinch.api.core.http + +import com.tryfinch.api.core.LogLevel +import com.tryfinch.api.core.RequestOptions +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream +import java.io.IOException +import java.io.InputStream +import java.io.OutputStream +import java.io.PrintStream +import java.nio.charset.StandardCharsets +import java.time.Clock +import java.time.Instant +import java.time.ZoneOffset +import java.util.concurrent.CompletableFuture +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.parallel.ResourceLock +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +@ResourceLock("stderr") +internal class LoggingHttpClientTest { + + private lateinit var originalErr: PrintStream + private lateinit var errContent: ByteArrayOutputStream + + @BeforeEach + fun beforeEach() { + originalErr = System.err + errContent = ByteArrayOutputStream() + System.setErr(PrintStream(errContent)) + } + + @AfterEach + fun afterEach() { + System.setErr(originalErr) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun offLevel_noOutput(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.OFF) + + val response = client.execute(simpleGetRequest(), async).apply { body().readBytes() } + + assertThat(response.statusCode()).isEqualTo(200) + assertThat(stderrOutput()).isEmpty() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsGetRequest(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.INFO) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsPostRequestWithBodySize(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.INFO) + + client.execute(postRequestWithBody("""{"key":"value"}"""), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> POST https://api.example.com/v1/resources (15-byte body) + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsRequestWithUnknownLengthBody(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.INFO) + + client + .execute(postRequestWithBody("""{"key":"value"}""", contentLength = -1L), async) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> POST https://api.example.com/v1/resources (unknown-length body) + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsResponseStatusAndDuration(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:00:01.234Z"), + ) + val client = loggingClient(fakeHttpClient(statusCode = 201), LogLevel.INFO, clock) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 201 (1s 234ms) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_logsResponseContentLength(async: Boolean) { + val headers = + Headers.builder().put("Content-Length", "42").put("Content-Type", "text/plain").build() + val client = loggingClient(fakeHttpClient(responseHeaders = headers), LogLevel.INFO) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (0s, 42-byte body) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_doesNotLogHeaders(async: Boolean) { + val headers = Headers.builder().put("X-Custom", "visible").build() + val client = loggingClient(fakeHttpClient(responseHeaders = headers), LogLevel.INFO) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("v1") + .putHeader("X-Request-Custom", "req-value") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1 + |<-- 200 (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsGetWithEndMarker(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.DEBUG) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsRequestAndResponseHeaders(async: Boolean) { + val responseHeaders = + Headers.builder() + .put("X-Response-Id", "abc-123") + .put("Content-Type", "text/plain") + .build() + val client = + loggingClient(fakeHttpClient(responseHeaders = responseHeaders), LogLevel.DEBUG) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("test") + .putHeader("X-Custom", "my-value") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/test + |X-Custom: my-value + |--> END GET + | + |<-- 200 (0s) + |Content-Type: text/plain + |X-Response-Id: abc-123 + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_redactsSensitiveHeaders(async: Boolean) { + val client = + loggingClient( + fakeHttpClient(), + LogLevel.DEBUG, + redactedHeaders = setOf("Authorization", "X-Secret"), + ) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("test") + .putHeader("Authorization", "Bearer token-123") + .putHeader("X-Secret", "secret-value") + .putHeader("X-Public", "public-value") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/test + |Authorization: ██ + |X-Public: public-value + |X-Secret: ██ + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_redactsHeadersCaseInsensitively(async: Boolean) { + val client = + loggingClient( + fakeHttpClient(), + LogLevel.DEBUG, + redactedHeaders = setOf("Authorization"), + ) + + client + .execute( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("test") + .putHeader("authorization", "Bearer secret") + .build(), + async, + ) + .body() + .readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/test + |authorization: ██ + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsRequestBody(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.DEBUG) + val body = """{"name":"test","value":42}""" + + client.execute(postRequestWithBody(body), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> POST https://api.example.com/v1/resources (26-byte body) + | + |{"name":"test","value":42} + |--> END POST (26-byte body) + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsResponseBody(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + val response = client.execute(simpleGetRequest(), async) + val body = response.body().readBytes().toString(StandardCharsets.UTF_8) + + assertThat(body).isEqualTo(responseBody) + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + | + |{"id":1,"status":"ok"} + |<-- END HTTP (22-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsBinaryResponseBodyAsOmitted(async: Boolean) { + val binaryBody = ByteArray(256) { it.toByte() } + val client = loggingClient(fakeHttpClient(responseBody = binaryBody), LogLevel.DEBUG) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + | + |(binary body omitted) + |<-- END HTTP (256-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsMultilineResponseBody(async: Boolean) { + val multilineBody = "line1\nline2\nline3" + val headers = Headers.builder().put("Content-Type", "text/plain; charset=utf-8").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = multilineBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: text/plain; charset=utf-8 + | + |line1 + |line2 + |line3 + |<-- END HTTP (17-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsResponseBodyWithExplicitCharset(async: Boolean) { + val responseBody = "héllo wörld" + val headers = Headers.builder().put("Content-Type", "text/plain; charset=utf-8").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: text/plain; charset=utf-8 + | + |héllo wörld + |<-- END HTTP (13-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsResponseBodyWithNoContentType(async: Boolean) { + val responseBody = "plain text body" + val client = + loggingClient( + fakeHttpClient(responseBody = responseBody.toByteArray(StandardCharsets.UTF_8)), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + | + |plain text body + |<-- END HTTP (15-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEmptyResponseBody(async: Boolean) { + val client = loggingClient(fakeHttpClient(), LogLevel.DEBUG) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |<-- END HTTP (0-byte body) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEndHttpMarkerOnEarlyClose(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + val body = client.execute(simpleGetRequest(), async).body() + body.read(ByteArray(5)) + body.close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + | + |{"id" + |<-- END HTTP (5-byte body, closed early) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEndHttpMarkerOnCloseWithoutReading(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).body().close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + |<-- END HTTP (0-byte body, closed early) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsEndHttpMarkerWhenResponseClosedAfterPartialRead(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + val response = client.execute(simpleGetRequest(), async) + response.body().read(ByteArray(5)) + response.close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + | + |{"id" + |<-- END HTTP (5-byte body, closed early) + | + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_doesNotLogEndHttpMarkerWhenResponseClosedWithoutBodyAccess(async: Boolean) { + val responseBody = """{"id":1,"status":"ok"}""" + val headers = Headers.builder().put("Content-Type", "application/json").build() + val client = + loggingClient( + fakeHttpClient( + responseHeaders = headers, + responseBody = responseBody.toByteArray(StandardCharsets.UTF_8), + ), + LogLevel.DEBUG, + ) + + client.execute(simpleGetRequest(), async).close() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- 200 (0s) + |Content-Type: application/json + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun errorLevel_logsRequestFailure(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:00:01.234Z"), + ) + val client = + loggingClient( + failingHttpClient(IOException("Connection refused")), + LogLevel.ERROR, + clock, + ) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- !! IOException: Connection refused (1s 234ms) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun infoLevel_doesNotLogRequestFailure(async: Boolean) { + val client = + loggingClient(failingHttpClient(IOException("Connection refused")), LogLevel.INFO) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun debugLevel_logsRequestFailureAfterHeaders(async: Boolean) { + val client = + loggingClient(failingHttpClient(IOException("Connection refused")), LogLevel.DEBUG) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |--> END GET + | + |<-- !! IOException: Connection refused (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun errorLevel_logsRequestFailureWithoutMessage(async: Boolean) { + val client = loggingClient(failingHttpClient(IOException()), LogLevel.ERROR) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- !! IOException (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun offLevel_doesNotLogRequestFailure(async: Boolean) { + val client = + loggingClient(failingHttpClient(IOException("Connection refused")), LogLevel.OFF) + + assertThatThrownBy { client.execute(simpleGetRequest(), async) } + + assertThat(stderrOutput()).isEmpty() + } + + @Test + fun errorLevel_logsExecuteAsyncSynchronousThrow() { + val error = IOException("Connection refused") + val client = + loggingClient( + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = throw UnsupportedOperationException() + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture = throw error + + override fun close() {} + }, + LogLevel.ERROR, + ) + + assertThatThrownBy { client.execute(simpleGetRequest(), async = true) }.isSameAs(error) + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- !! IOException: Connection refused (0s) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun durationFormat_seconds(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:00:02.500Z"), + ) + val client = loggingClient(fakeHttpClient(), LogLevel.INFO, clock) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (2s 500ms) + |""" + .trimMargin() + ) + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun durationFormat_minutesAndSeconds(async: Boolean) { + val clock = + clockFrom( + Instant.parse("1998-04-21T00:00:00Z"), + Instant.parse("1998-04-21T00:01:40.467Z"), + ) + val client = loggingClient(fakeHttpClient(), LogLevel.INFO, clock) + + client.execute(simpleGetRequest(), async).body().readBytes() + + assertThat(stderrOutput()) + .isEqualTo( + """ + |--> GET https://api.example.com/v1/resources + |<-- 200 (1m 40s 467ms) + |""" + .trimMargin() + ) + } + + @Test + fun builder_toBuilder_roundtrips() { + val delegate = fakeHttpClient() + val clock = Clock.fixed(Instant.parse("1998-04-21T00:00:00Z"), ZoneOffset.UTC) + val client = + LoggingHttpClient.builder() + .httpClient(delegate) + .level(LogLevel.DEBUG) + .redactedHeaders(setOf("X-Secret")) + .clock(clock) + .build() + + val rebuilt = client.toBuilder().build() + + assertThat(rebuilt.httpClient).isSameAs(delegate) + assertThat(rebuilt.level).isEqualTo(LogLevel.DEBUG) + assertThat(rebuilt.redactedHeaders).containsExactly("X-Secret") + assertThat(rebuilt.clock).isEqualTo(clock) + } + + @Test + fun close_delegatesToUnderlyingClient() { + var closed = false + val delegate = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = throw UnsupportedOperationException() + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture = throw UnsupportedOperationException() + + override fun close() { + closed = true + } + } + val client = loggingClient(delegate, LogLevel.OFF) + + client.close() + + assertThat(closed).isTrue() + } + + private fun stderrOutput(): String = errContent.toString("UTF-8") + + private fun loggingClient( + httpClient: HttpClient, + level: LogLevel, + clock: Clock = clockFrom(Instant.parse("1998-04-21T00:00:00Z")), + redactedHeaders: Set = + setOf("authorization", "api-key", "x-api-key", "cookie", "set-cookie"), + ): LoggingHttpClient = + LoggingHttpClient.builder() + .httpClient(httpClient) + .level(level) + .clock(clock) + .redactedHeaders(redactedHeaders) + .build() + + private fun simpleGetRequest(): HttpRequest = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("v1") + .addPathSegment("resources") + .build() + + private fun postRequestWithBody( + body: String, + contentType: String = "application/json", + contentLength: Long? = null, + ): HttpRequest = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl("https://api.example.com") + .addPathSegment("v1") + .addPathSegment("resources") + .body( + object : HttpRequestBody { + private val bytes = body.toByteArray(StandardCharsets.UTF_8) + + override fun writeTo(outputStream: OutputStream) { + outputStream.write(bytes) + } + + override fun contentType(): String = contentType + + override fun contentLength(): Long = contentLength ?: bytes.size.toLong() + + override fun repeatable(): Boolean = true + + override fun close() {} + } + ) + .build() + + private fun fakeHttpClient( + statusCode: Int = 200, + responseHeaders: Headers = Headers.builder().build(), + responseBody: ByteArray = ByteArray(0), + ): HttpClient = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + // Consume the request body if present to trigger logging. + request.body?.let { + val out = ByteArrayOutputStream() + it.writeTo(out) + } + return fakeResponse(statusCode, responseHeaders, responseBody) + } + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture = + CompletableFuture.completedFuture(execute(request, requestOptions)) + + override fun close() {} + } + + private fun failingHttpClient(error: Throwable): HttpClient = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + request.body?.let { + val out = ByteArrayOutputStream() + it.writeTo(out) + } + throw error + } + + override fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): CompletableFuture { + val future = CompletableFuture() + future.completeExceptionally(error) + return future + } + + override fun close() {} + } + + private fun fakeResponse(statusCode: Int, headers: Headers, body: ByteArray): HttpResponse = + object : HttpResponse { + override fun statusCode(): Int = statusCode + + override fun headers(): Headers = headers + + override fun body(): InputStream = ByteArrayInputStream(body) + + override fun close() {} + } + + private fun clockFrom(vararg instants: Instant): Clock = + object : Clock() { + private var index = 0 + + override fun getZone() = ZoneOffset.UTC + + override fun withZone(zone: java.time.ZoneId?) = this + + override fun instant(): Instant { + val instant = instants[index % instants.size] + index++ + return instant + } + } + + private fun HttpClient.execute(request: HttpRequest, async: Boolean): HttpResponse = + if (async) executeAsync(request).get() else execute(request) +} diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/RetryingHttpClientTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/RetryingHttpClientTest.kt index 224772646..98600b4a4 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/RetryingHttpClientTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/core/http/RetryingHttpClientTest.kt @@ -1,6 +1,17 @@ +// File generated from our OpenAPI spec by Stainless. + package com.tryfinch.api.core.http -import com.github.tomakehurst.wiremock.client.WireMock.* +import com.github.tomakehurst.wiremock.client.WireMock.equalTo +import com.github.tomakehurst.wiremock.client.WireMock.matching +import com.github.tomakehurst.wiremock.client.WireMock.ok +import com.github.tomakehurst.wiremock.client.WireMock.post +import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor +import com.github.tomakehurst.wiremock.client.WireMock.resetAllScenarios +import com.github.tomakehurst.wiremock.client.WireMock.serviceUnavailable +import com.github.tomakehurst.wiremock.client.WireMock.stubFor +import com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo +import com.github.tomakehurst.wiremock.client.WireMock.verify import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo import com.github.tomakehurst.wiremock.junit5.WireMockTest import com.github.tomakehurst.wiremock.stubbing.Scenario @@ -9,7 +20,11 @@ import com.tryfinch.api.core.RequestOptions import com.tryfinch.api.core.Sleeper import com.tryfinch.api.errors.FinchRetryableException import java.io.InputStream +import java.time.Clock import java.time.Duration +import java.time.OffsetDateTime +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter import java.util.concurrent.CompletableFuture import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.BeforeEach @@ -25,6 +40,21 @@ internal class RetryingHttpClientTest { private lateinit var baseUrl: String private lateinit var httpClient: HttpClient + private class RecordingSleeper : Sleeper { + val durations = mutableListOf() + + override fun sleep(duration: Duration) { + durations.add(duration) + } + + override fun sleepAsync(duration: Duration): CompletableFuture { + durations.add(duration) + return CompletableFuture.completedFuture(null) + } + + override fun close() {} + } + @BeforeEach fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { baseUrl = wmRuntimeInfo.httpBaseUrl @@ -75,7 +105,8 @@ internal class RetryingHttpClientTest { @ValueSource(booleans = [false, true]) fun execute(async: Boolean) { stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) - val retryingClient = retryingHttpClientBuilder().build() + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).build() val response = retryingClient.execute( @@ -89,6 +120,7 @@ internal class RetryingHttpClientTest { assertThat(response.statusCode()).isEqualTo(200) verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).isEmpty() assertNoResponseLeaks() } @@ -100,8 +132,12 @@ internal class RetryingHttpClientTest { .withHeader("X-Some-Header", matching("stainless-java-retry-.+")) .willReturn(ok()) ) + val sleeper = RecordingSleeper() val retryingClient = - retryingHttpClientBuilder().maxRetries(2).idempotencyHeader("X-Some-Header").build() + retryingHttpClientBuilder(sleeper) + .maxRetries(2) + .idempotencyHeader("X-Some-Header") + .build() val response = retryingClient.execute( @@ -115,20 +151,20 @@ internal class RetryingHttpClientTest { assertThat(response.statusCode()).isEqualTo(200) verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).isEmpty() assertNoResponseLeaks() } @ParameterizedTest @ValueSource(booleans = [false, true]) fun execute_withRetryAfterHeader(async: Boolean) { + val retryAfterDate = "Wed, 21 Oct 2015 07:28:00 GMT" stubFor( post(urlPathEqualTo("/something")) // First we fail with a retry after header given as a date .inScenario("foo") .whenScenarioStateIs(Scenario.STARTED) - .willReturn( - serviceUnavailable().withHeader("Retry-After", "Wed, 21 Oct 2015 07:28:00 GMT") - ) + .willReturn(serviceUnavailable().withHeader("Retry-After", retryAfterDate)) .willSetStateTo("RETRY_AFTER_DATE") ) stubFor( @@ -147,7 +183,13 @@ internal class RetryingHttpClientTest { .willReturn(ok()) .willSetStateTo("COMPLETED") ) - val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + // Fix the clock to 5 seconds before the Retry-After date so the date-based backoff is + // deterministic. + val retryAfterDateTime = + OffsetDateTime.parse(retryAfterDate, DateTimeFormatter.RFC_1123_DATE_TIME) + val clock = Clock.fixed(retryAfterDateTime.minusSeconds(5).toInstant(), ZoneOffset.UTC) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper, clock).maxRetries(2).build() val response = retryingClient.execute( @@ -175,19 +217,20 @@ internal class RetryingHttpClientTest { postRequestedFor(urlPathEqualTo("/something")) .withHeader("x-stainless-retry-count", equalTo("2")), ) + assertThat(sleeper.durations) + .containsExactly(Duration.ofSeconds(5), Duration.ofMillis(1234)) assertNoResponseLeaks() } @ParameterizedTest @ValueSource(booleans = [false, true]) fun execute_withOverwrittenRetryCountHeader(async: Boolean) { + val retryAfterDate = "Wed, 21 Oct 2015 07:28:00 GMT" stubFor( post(urlPathEqualTo("/something")) .inScenario("foo") // first we fail with a retry after header given as a date .whenScenarioStateIs(Scenario.STARTED) - .willReturn( - serviceUnavailable().withHeader("Retry-After", "Wed, 21 Oct 2015 07:28:00 GMT") - ) + .willReturn(serviceUnavailable().withHeader("Retry-After", retryAfterDate)) .willSetStateTo("RETRY_AFTER_DATE") ) stubFor( @@ -197,7 +240,11 @@ internal class RetryingHttpClientTest { .willReturn(ok()) .willSetStateTo("COMPLETED") ) - val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + val retryAfterDateTime = + OffsetDateTime.parse(retryAfterDate, DateTimeFormatter.RFC_1123_DATE_TIME) + val clock = Clock.fixed(retryAfterDateTime.minusSeconds(5).toInstant(), ZoneOffset.UTC) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper, clock).maxRetries(2).build() val response = retryingClient.execute( @@ -216,6 +263,7 @@ internal class RetryingHttpClientTest { postRequestedFor(urlPathEqualTo("/something")) .withHeader("x-stainless-retry-count", equalTo("42")), ) + assertThat(sleeper.durations).containsExactly(Duration.ofSeconds(5)) assertNoResponseLeaks() } @@ -236,7 +284,8 @@ internal class RetryingHttpClientTest { .willReturn(ok()) .willSetStateTo("COMPLETED") ) - val retryingClient = retryingHttpClientBuilder().maxRetries(1).build() + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(1).build() val response = retryingClient.execute( @@ -250,6 +299,7 @@ internal class RetryingHttpClientTest { assertThat(response.statusCode()).isEqualTo(200) verify(2, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).containsExactly(Duration.ofMillis(10)) assertNoResponseLeaks() } @@ -290,21 +340,12 @@ internal class RetryingHttpClientTest { override fun close() = httpClient.close() } + val sleeper = RecordingSleeper() val retryingClient = RetryingHttpClient.builder() .httpClient(failingHttpClient) .maxRetries(2) - .sleeper( - object : Sleeper { - - override fun sleep(duration: Duration) {} - - override fun sleepAsync(duration: Duration): CompletableFuture = - CompletableFuture.completedFuture(null) - - override fun close() {} - } - ) + .sleeper(sleeper) .build() val response = @@ -328,25 +369,153 @@ internal class RetryingHttpClientTest { postRequestedFor(urlPathEqualTo("/something")) .withHeader("x-stainless-retry-count", equalTo("0")), ) + // Exponential backoff with jitter: 0.5s * jitter where jitter is in [0.75, 1.0]. + assertThat(sleeper.durations).hasSize(1) + assertThat(sleeper.durations[0]).isBetween(Duration.ofMillis(375), Duration.ofMillis(500)) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withExponentialBackoff(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(serviceUnavailable())) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(3).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + // All retries exhausted; the last 503 response is returned. + assertThat(response.statusCode()).isEqualTo(503) + verify(4, postRequestedFor(urlPathEqualTo("/something"))) + // Exponential backoff with jitter: backoff = min(0.5 * 2^(retries-1), 8) * jitter where + // jitter is in [0.75, 1.0]. + assertThat(sleeper.durations).hasSize(3) + // retries=1: 0.5s * [0.75, 1.0] + assertThat(sleeper.durations[0]).isBetween(Duration.ofMillis(375), Duration.ofMillis(500)) + // retries=2: 1s * [0.75, 1.0] + assertThat(sleeper.durations[1]).isBetween(Duration.ofMillis(750), Duration.ofMillis(1000)) + // retries=3: 2s * [0.75, 1.0] + assertThat(sleeper.durations[2]).isBetween(Duration.ofMillis(1500), Duration.ofMillis(2000)) assertNoResponseLeaks() } - private fun retryingHttpClientBuilder() = - RetryingHttpClient.builder() - .httpClient(httpClient) - // Use a no-op `Sleeper` to make the test fast. - .sleeper( - object : Sleeper { + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withExponentialBackoffCap(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(serviceUnavailable())) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(6).build() - override fun sleep(duration: Duration) {} + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) - override fun sleepAsync(duration: Duration): CompletableFuture = - CompletableFuture.completedFuture(null) + assertThat(response.statusCode()).isEqualTo(503) + verify(7, postRequestedFor(urlPathEqualTo("/something"))) + assertThat(sleeper.durations).hasSize(6) + // retries=5: backoff hits the 8s cap * [0.75, 1.0] + assertThat(sleeper.durations[4]).isBetween(Duration.ofMillis(6000), Duration.ofMillis(8000)) + // retries=6: still capped at 8s * [0.75, 1.0] + assertThat(sleeper.durations[5]).isBetween(Duration.ofMillis(6000), Duration.ofMillis(8000)) + assertNoResponseLeaks() + } - override fun close() {} - } + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterMsPriorityOverRetryAfter(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn( + serviceUnavailable() + .withHeader("Retry-After-Ms", "50") + .withHeader("Retry-After", "2") + ) + .willSetStateTo("RETRY") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs("RETRY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(1).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + // Retry-After-Ms (50ms) takes priority over Retry-After (2s). + assertThat(sleeper.durations).containsExactly(Duration.ofMillis(50)) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterUnparseable(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(serviceUnavailable().withHeader("Retry-After", "not-a-date-or-number")) + .willSetStateTo("RETRY") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs("RETRY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val sleeper = RecordingSleeper() + val retryingClient = retryingHttpClientBuilder(sleeper).maxRetries(1).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, ) + assertThat(response.statusCode()).isEqualTo(200) + // Unparseable Retry-After falls through to exponential backoff. + assertThat(sleeper.durations).hasSize(1) + assertThat(sleeper.durations[0]).isBetween(Duration.ofMillis(375), Duration.ofMillis(500)) + assertNoResponseLeaks() + } + + private fun retryingHttpClientBuilder( + sleeper: RecordingSleeper, + clock: Clock = Clock.systemUTC(), + ) = RetryingHttpClient.builder().httpClient(httpClient).sleeper(sleeper).clock(clock) + private fun HttpClient.execute(request: HttpRequest, async: Boolean): HttpResponse = if (async) executeAsync(request).get() else execute(request) diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/AccountUpdateEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/AccountUpdateEventTest.kt index 2ebf051e2..e462836ca 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/AccountUpdateEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/AccountUpdateEventTest.kt @@ -16,6 +16,7 @@ internal class AccountUpdateEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( AccountUpdateEvent.Data.builder() .authenticationMethod( @@ -942,6 +943,7 @@ internal class AccountUpdateEventTest { assertThat(accountUpdateEvent.accountId()).isEqualTo("account_id") assertThat(accountUpdateEvent.companyId()).isEqualTo("company_id") assertThat(accountUpdateEvent.connectionId()).contains("connection_id") + assertThat(accountUpdateEvent.entityId()).contains("entity_id") assertThat(accountUpdateEvent.data()) .contains( AccountUpdateEvent.Data.builder() @@ -1814,6 +1816,7 @@ internal class AccountUpdateEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( AccountUpdateEvent.Data.builder() .authenticationMethod( diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BaseWebhookEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BaseWebhookEventTest.kt index 1c0999b9e..bdb5f23f8 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BaseWebhookEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BaseWebhookEventTest.kt @@ -16,11 +16,13 @@ internal class BaseWebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .build() assertThat(baseWebhookEvent.accountId()).isEqualTo("account_id") assertThat(baseWebhookEvent.companyId()).isEqualTo("company_id") assertThat(baseWebhookEvent.connectionId()).contains("connection_id") + assertThat(baseWebhookEvent.entityId()).contains("entity_id") } @Test @@ -31,6 +33,7 @@ internal class BaseWebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .build() val roundtrippedBaseWebhookEvent = diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BenefitContributionTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BenefitContributionTest.kt index 15b625c92..b151c5927 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BenefitContributionTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/BenefitContributionTest.kt @@ -15,28 +15,28 @@ import org.junit.jupiter.params.provider.EnumSource internal class BenefitContributionTest { @Test - fun ofUnionMember0() { - val unionMember0 = - BenefitContribution.UnionMember0.builder() + fun ofFixed() { + val fixed = + BenefitContribution.BenefitContributionFixed.builder() .amount(0L) - .type(BenefitContribution.UnionMember0.Type.FIXED) + .type(BenefitContribution.BenefitContributionFixed.Type.FIXED) .build() - val benefitContribution = BenefitContribution.ofUnionMember0(unionMember0) + val benefitContribution = BenefitContribution.ofFixed(fixed) - assertThat(benefitContribution.unionMember0()).contains(unionMember0) - assertThat(benefitContribution.unionMember1()).isEmpty - assertThat(benefitContribution.unionMember2()).isEmpty + assertThat(benefitContribution.fixed()).contains(fixed) + assertThat(benefitContribution.percent()).isEmpty + assertThat(benefitContribution.tiered()).isEmpty } @Test - fun ofUnionMember0Roundtrip() { + fun ofFixedRoundtrip() { val jsonMapper = jsonMapper() val benefitContribution = - BenefitContribution.ofUnionMember0( - BenefitContribution.UnionMember0.builder() + BenefitContribution.ofFixed( + BenefitContribution.BenefitContributionFixed.builder() .amount(0L) - .type(BenefitContribution.UnionMember0.Type.FIXED) + .type(BenefitContribution.BenefitContributionFixed.Type.FIXED) .build() ) @@ -50,28 +50,28 @@ internal class BenefitContributionTest { } @Test - fun ofUnionMember1() { - val unionMember1 = - BenefitContribution.UnionMember1.builder() + fun ofPercent() { + val percent = + BenefitContribution.BenefitContributionPercent.builder() .amount(0L) - .type(BenefitContribution.UnionMember1.Type.PERCENT) + .type(BenefitContribution.BenefitContributionPercent.Type.PERCENT) .build() - val benefitContribution = BenefitContribution.ofUnionMember1(unionMember1) + val benefitContribution = BenefitContribution.ofPercent(percent) - assertThat(benefitContribution.unionMember0()).isEmpty - assertThat(benefitContribution.unionMember1()).contains(unionMember1) - assertThat(benefitContribution.unionMember2()).isEmpty + assertThat(benefitContribution.fixed()).isEmpty + assertThat(benefitContribution.percent()).contains(percent) + assertThat(benefitContribution.tiered()).isEmpty } @Test - fun ofUnionMember1Roundtrip() { + fun ofPercentRoundtrip() { val jsonMapper = jsonMapper() val benefitContribution = - BenefitContribution.ofUnionMember1( - BenefitContribution.UnionMember1.builder() + BenefitContribution.ofPercent( + BenefitContribution.BenefitContributionPercent.builder() .amount(0L) - .type(BenefitContribution.UnionMember1.Type.PERCENT) + .type(BenefitContribution.BenefitContributionPercent.Type.PERCENT) .build() ) @@ -85,35 +85,38 @@ internal class BenefitContributionTest { } @Test - fun ofUnionMember2() { - val unionMember2 = - BenefitContribution.UnionMember2.builder() + fun ofTiered() { + val tiered = + BenefitContribution.BenefitContributionTiered.builder() .addTier( - BenefitContribution.UnionMember2.Tier.builder().match(1L).threshold(1L).build() + BenefitContribution.BenefitContributionTiered.Tier.builder() + .match(1L) + .threshold(1L) + .build() ) - .type(BenefitContribution.UnionMember2.Type.TIERED) + .type(BenefitContribution.BenefitContributionTiered.Type.TIERED) .build() - val benefitContribution = BenefitContribution.ofUnionMember2(unionMember2) + val benefitContribution = BenefitContribution.ofTiered(tiered) - assertThat(benefitContribution.unionMember0()).isEmpty - assertThat(benefitContribution.unionMember1()).isEmpty - assertThat(benefitContribution.unionMember2()).contains(unionMember2) + assertThat(benefitContribution.fixed()).isEmpty + assertThat(benefitContribution.percent()).isEmpty + assertThat(benefitContribution.tiered()).contains(tiered) } @Test - fun ofUnionMember2Roundtrip() { + fun ofTieredRoundtrip() { val jsonMapper = jsonMapper() val benefitContribution = - BenefitContribution.ofUnionMember2( - BenefitContribution.UnionMember2.builder() + BenefitContribution.ofTiered( + BenefitContribution.BenefitContributionTiered.builder() .addTier( - BenefitContribution.UnionMember2.Tier.builder() + BenefitContribution.BenefitContributionTiered.Tier.builder() .match(1L) .threshold(1L) .build() ) - .type(BenefitContribution.UnionMember2.Type.TIERED) + .type(BenefitContribution.BenefitContributionTiered.Type.TIERED) .build() ) diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CompanyEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CompanyEventTest.kt index 91f000b6b..755cc4bce 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CompanyEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CompanyEventTest.kt @@ -17,6 +17,7 @@ internal class CompanyEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( CompanyEvent.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) @@ -28,6 +29,7 @@ internal class CompanyEventTest { assertThat(companyEvent.accountId()).isEqualTo("account_id") assertThat(companyEvent.companyId()).isEqualTo("company_id") assertThat(companyEvent.connectionId()).contains("connection_id") + assertThat(companyEvent.entityId()).contains("entity_id") assertThat(companyEvent.data()) .contains( CompanyEvent.Data.builder() @@ -45,6 +47,7 @@ internal class CompanyEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( CompanyEvent.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CreateAccessTokenResponseTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CreateAccessTokenResponseTest.kt index e91e78dce..c7c22ab39 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CreateAccessTokenResponseTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/CreateAccessTokenResponseTest.kt @@ -24,6 +24,7 @@ internal class CreateAccessTokenResponseTest { .accountId("account_id") .companyId("company_id") .customerId("customer_id") + .customerName("customer_name") .build() assertThat(createAccessTokenResponse.accessToken()).isEqualTo("access_token") @@ -40,6 +41,7 @@ internal class CreateAccessTokenResponseTest { assertThat(createAccessTokenResponse.accountId()).contains("account_id") assertThat(createAccessTokenResponse.companyId()).contains("company_id") assertThat(createAccessTokenResponse.customerId()).contains("customer_id") + assertThat(createAccessTokenResponse.customerName()).contains("customer_name") } @Test @@ -58,6 +60,7 @@ internal class CreateAccessTokenResponseTest { .accountId("account_id") .companyId("company_id") .customerId("customer_id") + .customerName("customer_name") .build() val roundtrippedCreateAccessTokenResponse = diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/DirectoryEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/DirectoryEventTest.kt index 37a917e11..b03208ea8 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/DirectoryEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/DirectoryEventTest.kt @@ -16,6 +16,7 @@ internal class DirectoryEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(DirectoryEvent.Data.builder().individualId("individual_id").build()) .eventType(DirectoryEvent.EventType.DIRECTORY_CREATED) .build() @@ -23,6 +24,7 @@ internal class DirectoryEventTest { assertThat(directoryEvent.accountId()).isEqualTo("account_id") assertThat(directoryEvent.companyId()).isEqualTo("company_id") assertThat(directoryEvent.connectionId()).contains("connection_id") + assertThat(directoryEvent.entityId()).contains("entity_id") assertThat(directoryEvent.data()) .contains(DirectoryEvent.Data.builder().individualId("individual_id").build()) assertThat(directoryEvent.eventType()).contains(DirectoryEvent.EventType.DIRECTORY_CREATED) @@ -36,6 +38,7 @@ internal class DirectoryEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(DirectoryEvent.Data.builder().individualId("individual_id").build()) .eventType(DirectoryEvent.EventType.DIRECTORY_CREATED) .build() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataResponseTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataResponseTest.kt index 1fe2d86cd..12166db6f 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataResponseTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataResponseTest.kt @@ -15,21 +15,28 @@ internal class EmploymentDataResponseTest { val employmentDataResponse = EmploymentDataResponse.builder() .body( - EmploymentData.UnionMember0.builder() + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") .department( - EmploymentData.UnionMember0.Department.builder().name("name").build() + EmploymentData.InnerEmploymentData.Department.builder() + .name("name") + .build() ) .employment( - EmploymentData.UnionMember0.Employment.builder() - .subtype(EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) + EmploymentData.InnerEmploymentData.Employment.builder() + .subtype( + EmploymentData.InnerEmploymentData.Employment.Subtype.FULL_TIME + ) + .type(EmploymentData.InnerEmploymentData.Employment.Type.EMPLOYEE) .build() ) - .employmentStatus(EmploymentData.UnionMember0.EmploymentStatus.ACTIVE) + .employmentStatus( + EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE + ) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -46,7 +53,7 @@ internal class EmploymentDataResponseTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -54,7 +61,7 @@ internal class EmploymentDataResponseTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() @@ -85,22 +92,29 @@ internal class EmploymentDataResponseTest { assertThat(employmentDataResponse.body()) .isEqualTo( - EmploymentData.ofUnionMember0( - EmploymentData.UnionMember0.builder() + EmploymentData.ofEmploymentData( + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") .department( - EmploymentData.UnionMember0.Department.builder().name("name").build() + EmploymentData.InnerEmploymentData.Department.builder() + .name("name") + .build() ) .employment( - EmploymentData.UnionMember0.Employment.builder() - .subtype(EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) + EmploymentData.InnerEmploymentData.Employment.builder() + .subtype( + EmploymentData.InnerEmploymentData.Employment.Subtype.FULL_TIME + ) + .type(EmploymentData.InnerEmploymentData.Employment.Type.EMPLOYEE) .build() ) - .employmentStatus(EmploymentData.UnionMember0.EmploymentStatus.ACTIVE) + .employmentStatus( + EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE + ) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -117,7 +131,7 @@ internal class EmploymentDataResponseTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -125,7 +139,7 @@ internal class EmploymentDataResponseTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() @@ -162,21 +176,28 @@ internal class EmploymentDataResponseTest { val employmentDataResponse = EmploymentDataResponse.builder() .body( - EmploymentData.UnionMember0.builder() + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") .department( - EmploymentData.UnionMember0.Department.builder().name("name").build() + EmploymentData.InnerEmploymentData.Department.builder() + .name("name") + .build() ) .employment( - EmploymentData.UnionMember0.Employment.builder() - .subtype(EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) + EmploymentData.InnerEmploymentData.Employment.builder() + .subtype( + EmploymentData.InnerEmploymentData.Employment.Subtype.FULL_TIME + ) + .type(EmploymentData.InnerEmploymentData.Employment.Type.EMPLOYEE) .build() ) - .employmentStatus(EmploymentData.UnionMember0.EmploymentStatus.ACTIVE) + .employmentStatus( + EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE + ) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -193,7 +214,7 @@ internal class EmploymentDataResponseTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -201,7 +222,7 @@ internal class EmploymentDataResponseTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataTest.kt index ea4f1a63c..149b6f32e 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentDataTest.kt @@ -16,21 +16,24 @@ import org.junit.jupiter.params.provider.EnumSource internal class EmploymentDataTest { @Test - fun ofUnionMember0() { - val unionMember0 = - EmploymentData.UnionMember0.builder() + fun ofEmploymentData() { + val employmentData = + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") - .department(EmploymentData.UnionMember0.Department.builder().name("name").build()) + .department( + EmploymentData.InnerEmploymentData.Department.builder().name("name").build() + ) .employment( - EmploymentData.UnionMember0.Employment.builder() - .subtype(EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) + EmploymentData.InnerEmploymentData.Employment.builder() + .subtype(EmploymentData.InnerEmploymentData.Employment.Subtype.FULL_TIME) + .type(EmploymentData.InnerEmploymentData.Employment.Type.EMPLOYEE) .build() ) - .employmentStatus(EmploymentData.UnionMember0.EmploymentStatus.ACTIVE) + .employmentStatus(EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -47,7 +50,7 @@ internal class EmploymentDataTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -55,7 +58,7 @@ internal class EmploymentDataTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() @@ -80,32 +83,35 @@ internal class EmploymentDataTest { .workId("work_id") .build() - val employmentData = EmploymentData.ofUnionMember0(unionMember0) + val employmentData = EmploymentData.ofEmploymentData(employmentData) - assertThat(employmentData.unionMember0()).contains(unionMember0) + assertThat(employmentData.employmentData()).contains(employmentData) assertThat(employmentData.batchError()).isEmpty } @Test - fun ofUnionMember0Roundtrip() { + fun ofEmploymentDataRoundtrip() { val jsonMapper = jsonMapper() val employmentData = - EmploymentData.ofUnionMember0( - EmploymentData.UnionMember0.builder() + EmploymentData.ofEmploymentData( + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") .department( - EmploymentData.UnionMember0.Department.builder().name("name").build() + EmploymentData.InnerEmploymentData.Department.builder().name("name").build() ) .employment( - EmploymentData.UnionMember0.Employment.builder() - .subtype(EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) + EmploymentData.InnerEmploymentData.Employment.builder() + .subtype( + EmploymentData.InnerEmploymentData.Employment.Subtype.FULL_TIME + ) + .type(EmploymentData.InnerEmploymentData.Employment.Type.EMPLOYEE) .build() ) - .employmentStatus(EmploymentData.UnionMember0.EmploymentStatus.ACTIVE) + .employmentStatus(EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -122,7 +128,7 @@ internal class EmploymentDataTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -130,7 +136,7 @@ internal class EmploymentDataTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() @@ -177,7 +183,7 @@ internal class EmploymentDataTest { val employmentData = EmploymentData.ofBatchError(batchError) - assertThat(employmentData.unionMember0()).isEmpty + assertThat(employmentData.employmentData()).isEmpty assertThat(employmentData.batchError()).contains(batchError) } diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentEventTest.kt index 30a66f97c..d1cd70bcb 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentEventTest.kt @@ -16,6 +16,7 @@ internal class EmploymentEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(EmploymentEvent.Data.builder().individualId("individual_id").build()) .eventType(EmploymentEvent.EventType.EMPLOYMENT_CREATED) .build() @@ -23,6 +24,7 @@ internal class EmploymentEventTest { assertThat(employmentEvent.accountId()).isEqualTo("account_id") assertThat(employmentEvent.companyId()).isEqualTo("company_id") assertThat(employmentEvent.connectionId()).contains("connection_id") + assertThat(employmentEvent.entityId()).contains("entity_id") assertThat(employmentEvent.data()) .contains(EmploymentEvent.Data.builder().individualId("individual_id").build()) assertThat(employmentEvent.eventType()) @@ -37,6 +39,7 @@ internal class EmploymentEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(EmploymentEvent.Data.builder().individualId("individual_id").build()) .eventType(EmploymentEvent.EventType.EMPLOYMENT_CREATED) .build() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentUpdateResponseTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentUpdateResponseTest.kt index e280855b8..ec5245ca4 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentUpdateResponseTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/EmploymentUpdateResponseTest.kt @@ -34,6 +34,7 @@ internal class EmploymentUpdateResponseTest { .employmentStatus(EmploymentUpdateResponse.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentUpdateResponse.FlsaStatus.EXEMPT) .income( Income.builder() .amount(0L) @@ -98,6 +99,8 @@ internal class EmploymentUpdateResponseTest { .contains(EmploymentUpdateResponse.EmploymentStatus.ACTIVE) assertThat(employmentUpdateResponse.endDate()).contains("end_date") assertThat(employmentUpdateResponse.firstName()).contains("first_name") + assertThat(employmentUpdateResponse.flsaStatus()) + .contains(EmploymentUpdateResponse.FlsaStatus.EXEMPT) assertThat(employmentUpdateResponse.income()) .contains( Income.builder() @@ -167,6 +170,7 @@ internal class EmploymentUpdateResponseTest { .employmentStatus(EmploymentUpdateResponse.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentUpdateResponse.FlsaStatus.EXEMPT) .income( Income.builder() .amount(0L) diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponseTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponseTest.kt index 837c94a48..e552acb4d 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponseTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisEmploymentRetrieveManyPageResponseTest.kt @@ -17,27 +17,32 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .addResponse( EmploymentDataResponse.builder() .body( - EmploymentData.UnionMember0.builder() + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") .department( - EmploymentData.UnionMember0.Department.builder() + EmploymentData.InnerEmploymentData.Department.builder() .name("name") .build() ) .employment( - EmploymentData.UnionMember0.Employment.builder() + EmploymentData.InnerEmploymentData.Employment.builder() .subtype( - EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME + EmploymentData.InnerEmploymentData.Employment.Subtype + .FULL_TIME + ) + .type( + EmploymentData.InnerEmploymentData.Employment.Type + .EMPLOYEE ) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) .build() ) .employmentStatus( - EmploymentData.UnionMember0.EmploymentStatus.ACTIVE + EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE ) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -54,7 +59,7 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -62,7 +67,7 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() @@ -97,25 +102,31 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .containsExactly( EmploymentDataResponse.builder() .body( - EmploymentData.UnionMember0.builder() + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") .department( - EmploymentData.UnionMember0.Department.builder() + EmploymentData.InnerEmploymentData.Department.builder() .name("name") .build() ) .employment( - EmploymentData.UnionMember0.Employment.builder() + EmploymentData.InnerEmploymentData.Employment.builder() .subtype( - EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME + EmploymentData.InnerEmploymentData.Employment.Subtype + .FULL_TIME + ) + .type( + EmploymentData.InnerEmploymentData.Employment.Type.EMPLOYEE ) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) .build() ) - .employmentStatus(EmploymentData.UnionMember0.EmploymentStatus.ACTIVE) + .employmentStatus( + EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE + ) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -132,7 +143,7 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -140,7 +151,7 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() @@ -179,27 +190,32 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .addResponse( EmploymentDataResponse.builder() .body( - EmploymentData.UnionMember0.builder() + EmploymentData.InnerEmploymentData.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .classCode("class_code") .department( - EmploymentData.UnionMember0.Department.builder() + EmploymentData.InnerEmploymentData.Department.builder() .name("name") .build() ) .employment( - EmploymentData.UnionMember0.Employment.builder() + EmploymentData.InnerEmploymentData.Employment.builder() .subtype( - EmploymentData.UnionMember0.Employment.Subtype.FULL_TIME + EmploymentData.InnerEmploymentData.Employment.Subtype + .FULL_TIME + ) + .type( + EmploymentData.InnerEmploymentData.Employment.Type + .EMPLOYEE ) - .type(EmploymentData.UnionMember0.Employment.Type.EMPLOYEE) .build() ) .employmentStatus( - EmploymentData.UnionMember0.EmploymentStatus.ACTIVE + EmploymentData.InnerEmploymentData.EmploymentStatus.ACTIVE ) .endDate("end_date") .firstName("first_name") + .flsaStatus(EmploymentData.InnerEmploymentData.FlsaStatus.EXEMPT) .isActive(true) .lastName("last_name") .latestRehireDate("latest_rehire_date") @@ -216,7 +232,7 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .build() ) .manager( - EmploymentData.UnionMember0.Manager.builder() + EmploymentData.InnerEmploymentData.Manager.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .build() ) @@ -224,7 +240,7 @@ internal class HrisEmploymentRetrieveManyPageResponseTest { .startDate("start_date") .title("title") .addCustomField( - EmploymentData.UnionMember0.CustomField.builder() + EmploymentData.InnerEmploymentData.CustomField.builder() .name("name") .value("string") .build() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponseTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponseTest.kt index 281945102..7cab01c63 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponseTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/HrisIndividualRetrieveManyPageResponseTest.kt @@ -16,18 +16,18 @@ internal class HrisIndividualRetrieveManyPageResponseTest { .addResponse( IndividualResponse.builder() .body( - Individual.UnionMember0.builder() + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -44,9 +44,9 @@ internal class HrisIndividualRetrieveManyPageResponseTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") @@ -63,18 +63,18 @@ internal class HrisIndividualRetrieveManyPageResponseTest { .containsExactly( IndividualResponse.builder() .body( - Individual.UnionMember0.builder() + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -91,9 +91,9 @@ internal class HrisIndividualRetrieveManyPageResponseTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") @@ -114,18 +114,18 @@ internal class HrisIndividualRetrieveManyPageResponseTest { .addResponse( IndividualResponse.builder() .body( - Individual.UnionMember0.builder() + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -142,9 +142,9 @@ internal class HrisIndividualRetrieveManyPageResponseTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualBenefitTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualBenefitTest.kt index d928b3741..0a8bf5376 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualBenefitTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualBenefitTest.kt @@ -14,36 +14,39 @@ internal class IndividualBenefitTest { val individualBenefit = IndividualBenefit.builder() .body( - IndividualBenefit.Body.UnionMember0.builder() + IndividualBenefit.Body.InnerIndividualBenefit.builder() .annualMaximum(0L) .catchUp(true) .companyContribution( - IndividualBenefit.Body.UnionMember0.CompanyContribution - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.CompanyContribution + .CompanyContributionFixed .builder() .amount(0L) .type( - IndividualBenefit.Body.UnionMember0.CompanyContribution - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit + .CompanyContribution + .CompanyContributionFixed .Type .FIXED ) .build() ) .employeeDeduction( - IndividualBenefit.Body.UnionMember0.EmployeeDeduction.InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.EmployeeDeduction + .EmployeeDeductionContributionFixed .builder() .amount(0L) .type( - IndividualBenefit.Body.UnionMember0.EmployeeDeduction - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.EmployeeDeduction + .EmployeeDeductionContributionFixed .Type .FIXED ) .build() ) .hsaContributionLimit( - IndividualBenefit.Body.UnionMember0.HsaContributionLimit.INDIVIDUAL + IndividualBenefit.Body.InnerIndividualBenefit.HsaContributionLimit + .INDIVIDUAL ) .build() ) @@ -53,37 +56,40 @@ internal class IndividualBenefitTest { assertThat(individualBenefit.body()) .isEqualTo( - IndividualBenefit.Body.ofUnionMember0( - IndividualBenefit.Body.UnionMember0.builder() + IndividualBenefit.Body.ofIndividualBenefit( + IndividualBenefit.Body.InnerIndividualBenefit.builder() .annualMaximum(0L) .catchUp(true) .companyContribution( - IndividualBenefit.Body.UnionMember0.CompanyContribution - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.CompanyContribution + .CompanyContributionFixed .builder() .amount(0L) .type( - IndividualBenefit.Body.UnionMember0.CompanyContribution - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit + .CompanyContribution + .CompanyContributionFixed .Type .FIXED ) .build() ) .employeeDeduction( - IndividualBenefit.Body.UnionMember0.EmployeeDeduction.InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.EmployeeDeduction + .EmployeeDeductionContributionFixed .builder() .amount(0L) .type( - IndividualBenefit.Body.UnionMember0.EmployeeDeduction - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.EmployeeDeduction + .EmployeeDeductionContributionFixed .Type .FIXED ) .build() ) .hsaContributionLimit( - IndividualBenefit.Body.UnionMember0.HsaContributionLimit.INDIVIDUAL + IndividualBenefit.Body.InnerIndividualBenefit.HsaContributionLimit + .INDIVIDUAL ) .build() ) @@ -98,36 +104,39 @@ internal class IndividualBenefitTest { val individualBenefit = IndividualBenefit.builder() .body( - IndividualBenefit.Body.UnionMember0.builder() + IndividualBenefit.Body.InnerIndividualBenefit.builder() .annualMaximum(0L) .catchUp(true) .companyContribution( - IndividualBenefit.Body.UnionMember0.CompanyContribution - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.CompanyContribution + .CompanyContributionFixed .builder() .amount(0L) .type( - IndividualBenefit.Body.UnionMember0.CompanyContribution - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit + .CompanyContribution + .CompanyContributionFixed .Type .FIXED ) .build() ) .employeeDeduction( - IndividualBenefit.Body.UnionMember0.EmployeeDeduction.InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.EmployeeDeduction + .EmployeeDeductionContributionFixed .builder() .amount(0L) .type( - IndividualBenefit.Body.UnionMember0.EmployeeDeduction - .InnerUnionMember0 + IndividualBenefit.Body.InnerIndividualBenefit.EmployeeDeduction + .EmployeeDeductionContributionFixed .Type .FIXED ) .build() ) .hsaContributionLimit( - IndividualBenefit.Body.UnionMember0.HsaContributionLimit.INDIVIDUAL + IndividualBenefit.Body.InnerIndividualBenefit.HsaContributionLimit + .INDIVIDUAL ) .build() ) diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualEventTest.kt index 3909ed855..160e35d52 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualEventTest.kt @@ -16,6 +16,7 @@ internal class IndividualEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(IndividualEvent.Data.builder().individualId("individual_id").build()) .eventType(IndividualEvent.EventType.INDIVIDUAL_CREATED) .build() @@ -23,6 +24,7 @@ internal class IndividualEventTest { assertThat(individualEvent.accountId()).isEqualTo("account_id") assertThat(individualEvent.companyId()).isEqualTo("company_id") assertThat(individualEvent.connectionId()).contains("connection_id") + assertThat(individualEvent.entityId()).contains("entity_id") assertThat(individualEvent.data()) .contains(IndividualEvent.Data.builder().individualId("individual_id").build()) assertThat(individualEvent.eventType()) @@ -37,6 +39,7 @@ internal class IndividualEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(IndividualEvent.Data.builder().individualId("individual_id").build()) .eventType(IndividualEvent.EventType.INDIVIDUAL_CREATED) .build() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualResponseTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualResponseTest.kt index 3f480bc39..cef47957a 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualResponseTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualResponseTest.kt @@ -14,18 +14,18 @@ internal class IndividualResponseTest { val individualResponse = IndividualResponse.builder() .body( - Individual.UnionMember0.builder() + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -42,9 +42,9 @@ internal class IndividualResponseTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") @@ -57,19 +57,19 @@ internal class IndividualResponseTest { assertThat(individualResponse.body()) .isEqualTo( - Individual.ofUnionMember0( - Individual.UnionMember0.builder() + Individual.ofIndividual( + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -86,9 +86,9 @@ internal class IndividualResponseTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") @@ -106,18 +106,18 @@ internal class IndividualResponseTest { val individualResponse = IndividualResponse.builder() .body( - Individual.UnionMember0.builder() + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -134,9 +134,9 @@ internal class IndividualResponseTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualTest.kt index b6ae2c0f4..50c2b6ec0 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IndividualTest.kt @@ -15,20 +15,20 @@ import org.junit.jupiter.params.provider.EnumSource internal class IndividualTest { @Test - fun ofUnionMember0() { - val unionMember0 = - Individual.UnionMember0.builder() + fun ofIndividual() { + val individual = + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -45,38 +45,38 @@ internal class IndividualTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") .ssn("ssn") .build() - val individual = Individual.ofUnionMember0(unionMember0) + val individual = Individual.ofIndividual(individual) - assertThat(individual.unionMember0()).contains(unionMember0) + assertThat(individual.individual()).contains(individual) assertThat(individual.batchError()).isEmpty } @Test - fun ofUnionMember0Roundtrip() { + fun ofIndividualRoundtrip() { val jsonMapper = jsonMapper() val individual = - Individual.ofUnionMember0( - Individual.UnionMember0.builder() + Individual.ofIndividual( + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -93,9 +93,9 @@ internal class IndividualTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") @@ -124,7 +124,7 @@ internal class IndividualTest { val individual = Individual.ofBatchError(batchError) - assertThat(individual.unionMember0()).isEmpty + assertThat(individual.individual()).isEmpty assertThat(individual.batchError()).contains(batchError) } diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IntrospectionTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IntrospectionTest.kt index 32809d98b..784e9596a 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IntrospectionTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/IntrospectionTest.kt @@ -55,6 +55,7 @@ internal class IntrospectionTest { .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .name("name") .sourceId("source_id") + .status(Introspection.MultiAccountEntity.EntityConnectionStatus.PENDING) .build() ) .manual(true) @@ -102,6 +103,7 @@ internal class IntrospectionTest { .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .name("name") .sourceId("source_id") + .status(Introspection.MultiAccountEntity.EntityConnectionStatus.PENDING) .build() ) assertThat(introspection.manual()).contains(true) @@ -154,6 +156,7 @@ internal class IntrospectionTest { .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .name("name") .sourceId("source_id") + .status(Introspection.MultiAccountEntity.EntityConnectionStatus.PENDING) .build() ) .manual(true) diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobAutomatedCreateParamsTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobAutomatedCreateParamsTest.kt index 05ceffa76..c8f444655 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobAutomatedCreateParamsTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobAutomatedCreateParamsTest.kt @@ -2,7 +2,6 @@ package com.tryfinch.api.models -import kotlin.jvm.optionals.getOrNull import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -17,15 +16,8 @@ internal class JobAutomatedCreateParamsTest { fun body() { val params = JobAutomatedCreateParams.builder().bodyDataSyncAll().build() - val body = params._body().getOrNull() + val body = params._body() assertThat(body).isEqualTo(JobAutomatedCreateParams.Body.ofDataSyncAll()) } - - @Test - fun bodyWithoutOptionalFields() { - val params = JobAutomatedCreateParams.builder().build() - - val body = params._body().getOrNull() - } } diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobCompletionEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobCompletionEventTest.kt index 0e56ec095..ecdf23728 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobCompletionEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/JobCompletionEventTest.kt @@ -16,6 +16,7 @@ internal class JobCompletionEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(JobCompletionEvent.Data.builder().jobId("job_id").jobUrl("job_url").build()) .eventType(JobCompletionEvent.EventType.JOB_BENEFIT_CREATE_COMPLETED) .build() @@ -23,6 +24,7 @@ internal class JobCompletionEventTest { assertThat(jobCompletionEvent.accountId()).isEqualTo("account_id") assertThat(jobCompletionEvent.companyId()).isEqualTo("company_id") assertThat(jobCompletionEvent.connectionId()).contains("connection_id") + assertThat(jobCompletionEvent.entityId()).contains("entity_id") assertThat(jobCompletionEvent.data()) .contains(JobCompletionEvent.Data.builder().jobId("job_id").jobUrl("job_url").build()) assertThat(jobCompletionEvent.eventType()) @@ -37,6 +39,7 @@ internal class JobCompletionEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(JobCompletionEvent.Data.builder().jobId("job_id").jobUrl("job_url").build()) .eventType(JobCompletionEvent.EventType.JOB_BENEFIT_CREATE_COMPLETED) .build() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PayStatementEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PayStatementEventTest.kt index 126bc319e..91ddfe429 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PayStatementEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PayStatementEventTest.kt @@ -16,6 +16,7 @@ internal class PayStatementEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PayStatementEvent.Data.builder() .individualId("individual_id") @@ -28,6 +29,7 @@ internal class PayStatementEventTest { assertThat(payStatementEvent.accountId()).isEqualTo("account_id") assertThat(payStatementEvent.companyId()).isEqualTo("company_id") assertThat(payStatementEvent.connectionId()).contains("connection_id") + assertThat(payStatementEvent.entityId()).contains("entity_id") assertThat(payStatementEvent.data()) .contains( PayStatementEvent.Data.builder() @@ -47,6 +49,7 @@ internal class PayStatementEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PayStatementEvent.Data.builder() .individualId("individual_id") diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PaymentEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PaymentEventTest.kt index f118ea2f3..d83a153cf 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PaymentEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/PaymentEventTest.kt @@ -16,6 +16,7 @@ internal class PaymentEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PaymentEvent.PaymentIdentifiers.builder() .payDate("pay_date") @@ -28,6 +29,7 @@ internal class PaymentEventTest { assertThat(paymentEvent.accountId()).isEqualTo("account_id") assertThat(paymentEvent.companyId()).isEqualTo("company_id") assertThat(paymentEvent.connectionId()).contains("connection_id") + assertThat(paymentEvent.entityId()).contains("entity_id") assertThat(paymentEvent.data()) .contains( PaymentEvent.PaymentIdentifiers.builder() @@ -46,6 +48,7 @@ internal class PaymentEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PaymentEvent.PaymentIdentifiers.builder() .payDate("pay_date") diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParamsTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParamsTest.kt index 17320a997..d2ef2228f 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParamsTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxDirectoryCreateParamsTest.kt @@ -56,6 +56,9 @@ internal class SandboxDirectoryCreateParamsTest { .endDate("end_date") .ethnicity(SandboxDirectoryCreateParams.IndividualOrEmployment.Ethnicity.ASIAN) .firstName("first_name") + .flsaStatus( + SandboxDirectoryCreateParams.IndividualOrEmployment.FlsaStatus.EXEMPT + ) .gender(SandboxDirectoryCreateParams.IndividualOrEmployment.Gender.FEMALE) .income( Income.builder() @@ -178,6 +181,9 @@ internal class SandboxDirectoryCreateParamsTest { SandboxDirectoryCreateParams.IndividualOrEmployment.Ethnicity.ASIAN ) .firstName("first_name") + .flsaStatus( + SandboxDirectoryCreateParams.IndividualOrEmployment.FlsaStatus.EXEMPT + ) .gender(SandboxDirectoryCreateParams.IndividualOrEmployment.Gender.FEMALE) .income( Income.builder() @@ -294,6 +300,9 @@ internal class SandboxDirectoryCreateParamsTest { .endDate("end_date") .ethnicity(SandboxDirectoryCreateParams.IndividualOrEmployment.Ethnicity.ASIAN) .firstName("first_name") + .flsaStatus( + SandboxDirectoryCreateParams.IndividualOrEmployment.FlsaStatus.EXEMPT + ) .gender(SandboxDirectoryCreateParams.IndividualOrEmployment.Gender.FEMALE) .income( Income.builder() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParamsTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParamsTest.kt index 5d37a553d..4703d0595 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParamsTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/SandboxEmploymentUpdateParamsTest.kt @@ -31,6 +31,7 @@ internal class SandboxEmploymentUpdateParamsTest { .employmentStatus(SandboxEmploymentUpdateParams.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(SandboxEmploymentUpdateParams.FlsaStatus.EXEMPT) .income( Income.builder() .amount(0L) @@ -105,6 +106,7 @@ internal class SandboxEmploymentUpdateParamsTest { .employmentStatus(SandboxEmploymentUpdateParams.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(SandboxEmploymentUpdateParams.FlsaStatus.EXEMPT) .income( Income.builder() .amount(0L) @@ -170,6 +172,7 @@ internal class SandboxEmploymentUpdateParamsTest { .contains(SandboxEmploymentUpdateParams.EmploymentStatus.ACTIVE) assertThat(body.endDate()).contains("end_date") assertThat(body.firstName()).contains("first_name") + assertThat(body.flsaStatus()).contains(SandboxEmploymentUpdateParams.FlsaStatus.EXEMPT) assertThat(body.income()) .contains( Income.builder() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/WebhookEventTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/WebhookEventTest.kt index dbcb91f9e..2fb55765b 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/models/WebhookEventTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/models/WebhookEventTest.kt @@ -21,6 +21,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( AccountUpdateEvent.Data.builder() .authenticationMethod( @@ -965,6 +966,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( AccountUpdateEvent.Data.builder() .authenticationMethod( @@ -2123,6 +2125,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(JobCompletionEvent.Data.builder().jobId("job_id").jobUrl("job_url").build()) .eventType(JobCompletionEvent.EventType.JOB_BENEFIT_CREATE_COMPLETED) .build() @@ -2148,6 +2151,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( JobCompletionEvent.Data.builder().jobId("job_id").jobUrl("job_url").build() ) @@ -2171,6 +2175,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( CompanyEvent.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) @@ -2200,6 +2205,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( CompanyEvent.Data.builder() .putAdditionalProperty("foo", JsonValue.from("bar")) @@ -2225,6 +2231,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(DirectoryEvent.Data.builder().individualId("individual_id").build()) .eventType(DirectoryEvent.EventType.DIRECTORY_CREATED) .build() @@ -2250,6 +2257,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(DirectoryEvent.Data.builder().individualId("individual_id").build()) .eventType(DirectoryEvent.EventType.DIRECTORY_CREATED) .build() @@ -2271,6 +2279,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(EmploymentEvent.Data.builder().individualId("individual_id").build()) .eventType(EmploymentEvent.EventType.EMPLOYMENT_CREATED) .build() @@ -2296,6 +2305,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(EmploymentEvent.Data.builder().individualId("individual_id").build()) .eventType(EmploymentEvent.EventType.EMPLOYMENT_CREATED) .build() @@ -2317,6 +2327,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(IndividualEvent.Data.builder().individualId("individual_id").build()) .eventType(IndividualEvent.EventType.INDIVIDUAL_CREATED) .build() @@ -2342,6 +2353,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data(IndividualEvent.Data.builder().individualId("individual_id").build()) .eventType(IndividualEvent.EventType.INDIVIDUAL_CREATED) .build() @@ -2363,6 +2375,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PaymentEvent.PaymentIdentifiers.builder() .payDate("pay_date") @@ -2393,6 +2406,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PaymentEvent.PaymentIdentifiers.builder() .payDate("pay_date") @@ -2419,6 +2433,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PayStatementEvent.Data.builder() .individualId("individual_id") @@ -2449,6 +2464,7 @@ internal class WebhookEventTest { .accountId("account_id") .companyId("company_id") .connectionId("connection_id") + .entityId("entity_id") .data( PayStatementEvent.Data.builder() .individualId("individual_id") diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncTest.kt index 689095724..8990581ed 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/jobs/AutomatedServiceAsyncTest.kt @@ -22,9 +22,7 @@ internal class AutomatedServiceAsyncTest { val automatedServiceAsync = client.jobs().automated() val automatedFuture = - automatedServiceAsync.create( - JobAutomatedCreateParams.builder().bodyDataSyncAll().build() - ) + automatedServiceAsync.create(JobAutomatedCreateParams.Body.ofDataSyncAll()) val automated = automatedFuture.get() automated.validate() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncTest.kt index 56484790a..e00a98ea7 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/DirectoryServiceAsyncTest.kt @@ -26,134 +26,126 @@ internal class DirectoryServiceAsyncTest { val directoriesFuture = directoryServiceAsync.create( - SandboxDirectoryCreateParams.builder() - .addBody( - SandboxDirectoryCreateParams.IndividualOrEmployment.builder() - .classCode("class_code") - .addCustomField( - SandboxDirectoryCreateParams.IndividualOrEmployment.CustomField - .builder() - .name("name") - .value(JsonValue.from(mapOf())) - .build() - ) - .department( - SandboxDirectoryCreateParams.IndividualOrEmployment.Department - .builder() - .name("name") - .build() - ) - .dob("dob") - .addEmail( - SandboxDirectoryCreateParams.IndividualOrEmployment.Email.builder() - .data("data") - .type( - SandboxDirectoryCreateParams.IndividualOrEmployment.Email - .Type - .WORK - ) - .build() - ) - .employment( - SandboxDirectoryCreateParams.IndividualOrEmployment.Employment - .builder() - .subtype( - SandboxDirectoryCreateParams.IndividualOrEmployment - .Employment - .Subtype - .FULL_TIME - ) - .type( - SandboxDirectoryCreateParams.IndividualOrEmployment - .Employment - .Type - .EMPLOYEE - ) - .build() - ) - .employmentStatus( - SandboxDirectoryCreateParams.IndividualOrEmployment.EmploymentStatus - .ACTIVE - ) - .encryptedSsn("encrypted_ssn") - .endDate("end_date") - .ethnicity( - SandboxDirectoryCreateParams.IndividualOrEmployment.Ethnicity.ASIAN - ) - .firstName("first_name") - .gender( - SandboxDirectoryCreateParams.IndividualOrEmployment.Gender.FEMALE - ) - .income( - Income.builder() - .amount(0L) - .currency("currency") - .effectiveDate(LocalDate.parse("2019-12-27")) - .unit(Income.Unit.YEARLY) - .build() - ) - .addIncomeHistory( - Income.builder() - .amount(0L) - .currency("currency") - .effectiveDate(LocalDate.parse("2019-12-27")) - .unit(Income.Unit.YEARLY) - .build() - ) - .isActive(true) - .lastName("last_name") - .latestRehireDate("latest_rehire_date") - .location( - Location.builder() - .city("city") - .country("country") - .line1("line1") - .line2("line2") - .postalCode("postal_code") - .state("state") - .name("name") - .sourceId("source_id") - .build() - ) - .manager( - SandboxDirectoryCreateParams.IndividualOrEmployment.Manager - .builder() - .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .build() - ) - .middleName("middle_name") - .addPhoneNumber( - SandboxDirectoryCreateParams.IndividualOrEmployment.PhoneNumber - .builder() - .data("data") - .type( - SandboxDirectoryCreateParams.IndividualOrEmployment - .PhoneNumber - .Type - .WORK - ) - .build() - ) - .preferredName("preferred_name") - .residence( - Location.builder() - .city("city") - .country("country") - .line1("line1") - .line2("line2") - .postalCode("postal_code") - .state("state") - .name("name") - .sourceId("source_id") - .build() - ) - .sourceId("source_id") - .ssn("ssn") - .startDate("start_date") - .title("title") - .build() - ) - .build() + listOf( + SandboxDirectoryCreateParams.IndividualOrEmployment.builder() + .classCode("class_code") + .addCustomField( + SandboxDirectoryCreateParams.IndividualOrEmployment.CustomField + .builder() + .name("name") + .value(JsonValue.from(mapOf())) + .build() + ) + .department( + SandboxDirectoryCreateParams.IndividualOrEmployment.Department.builder() + .name("name") + .build() + ) + .dob("dob") + .addEmail( + SandboxDirectoryCreateParams.IndividualOrEmployment.Email.builder() + .data("data") + .type( + SandboxDirectoryCreateParams.IndividualOrEmployment.Email.Type + .WORK + ) + .build() + ) + .employment( + SandboxDirectoryCreateParams.IndividualOrEmployment.Employment.builder() + .subtype( + SandboxDirectoryCreateParams.IndividualOrEmployment.Employment + .Subtype + .FULL_TIME + ) + .type( + SandboxDirectoryCreateParams.IndividualOrEmployment.Employment + .Type + .EMPLOYEE + ) + .build() + ) + .employmentStatus( + SandboxDirectoryCreateParams.IndividualOrEmployment.EmploymentStatus + .ACTIVE + ) + .encryptedSsn("encrypted_ssn") + .endDate("end_date") + .ethnicity( + SandboxDirectoryCreateParams.IndividualOrEmployment.Ethnicity.ASIAN + ) + .firstName("first_name") + .flsaStatus( + SandboxDirectoryCreateParams.IndividualOrEmployment.FlsaStatus.EXEMPT + ) + .gender(SandboxDirectoryCreateParams.IndividualOrEmployment.Gender.FEMALE) + .income( + Income.builder() + .amount(0L) + .currency("currency") + .effectiveDate(LocalDate.parse("2019-12-27")) + .unit(Income.Unit.YEARLY) + .build() + ) + .addIncomeHistory( + Income.builder() + .amount(0L) + .currency("currency") + .effectiveDate(LocalDate.parse("2019-12-27")) + .unit(Income.Unit.YEARLY) + .build() + ) + .isActive(true) + .lastName("last_name") + .latestRehireDate("latest_rehire_date") + .location( + Location.builder() + .city("city") + .country("country") + .line1("line1") + .line2("line2") + .postalCode("postal_code") + .state("state") + .name("name") + .sourceId("source_id") + .build() + ) + .manager( + SandboxDirectoryCreateParams.IndividualOrEmployment.Manager.builder() + .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .middleName("middle_name") + .addPhoneNumber( + SandboxDirectoryCreateParams.IndividualOrEmployment.PhoneNumber + .builder() + .data("data") + .type( + SandboxDirectoryCreateParams.IndividualOrEmployment.PhoneNumber + .Type + .WORK + ) + .build() + ) + .preferredName("preferred_name") + .residence( + Location.builder() + .city("city") + .country("country") + .line1("line1") + .line2("line2") + .postalCode("postal_code") + .state("state") + .name("name") + .sourceId("source_id") + .build() + ) + .sourceId("source_id") + .ssn("ssn") + .startDate("start_date") + .title("title") + .build() + ) ) val directories = directoriesFuture.get() diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncTest.kt index 6fa1664b0..219b0296f 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/async/sandbox/EmploymentServiceAsyncTest.kt @@ -47,6 +47,7 @@ internal class EmploymentServiceAsyncTest { .employmentStatus(SandboxEmploymentUpdateParams.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(SandboxEmploymentUpdateParams.FlsaStatus.EXEMPT) .income( Income.builder() .amount(0L) diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceTest.kt index e4121bc5b..e4798add5 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/jobs/AutomatedServiceTest.kt @@ -21,8 +21,7 @@ internal class AutomatedServiceTest { .build() val automatedService = client.jobs().automated() - val automated = - automatedService.create(JobAutomatedCreateParams.builder().bodyDataSyncAll().build()) + val automated = automatedService.create(JobAutomatedCreateParams.Body.ofDataSyncAll()) automated.validate() } diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceTest.kt index b14c55a92..8e7f0e67a 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/DirectoryServiceTest.kt @@ -26,134 +26,126 @@ internal class DirectoryServiceTest { val directories = directoryService.create( - SandboxDirectoryCreateParams.builder() - .addBody( - SandboxDirectoryCreateParams.IndividualOrEmployment.builder() - .classCode("class_code") - .addCustomField( - SandboxDirectoryCreateParams.IndividualOrEmployment.CustomField - .builder() - .name("name") - .value(JsonValue.from(mapOf())) - .build() - ) - .department( - SandboxDirectoryCreateParams.IndividualOrEmployment.Department - .builder() - .name("name") - .build() - ) - .dob("dob") - .addEmail( - SandboxDirectoryCreateParams.IndividualOrEmployment.Email.builder() - .data("data") - .type( - SandboxDirectoryCreateParams.IndividualOrEmployment.Email - .Type - .WORK - ) - .build() - ) - .employment( - SandboxDirectoryCreateParams.IndividualOrEmployment.Employment - .builder() - .subtype( - SandboxDirectoryCreateParams.IndividualOrEmployment - .Employment - .Subtype - .FULL_TIME - ) - .type( - SandboxDirectoryCreateParams.IndividualOrEmployment - .Employment - .Type - .EMPLOYEE - ) - .build() - ) - .employmentStatus( - SandboxDirectoryCreateParams.IndividualOrEmployment.EmploymentStatus - .ACTIVE - ) - .encryptedSsn("encrypted_ssn") - .endDate("end_date") - .ethnicity( - SandboxDirectoryCreateParams.IndividualOrEmployment.Ethnicity.ASIAN - ) - .firstName("first_name") - .gender( - SandboxDirectoryCreateParams.IndividualOrEmployment.Gender.FEMALE - ) - .income( - Income.builder() - .amount(0L) - .currency("currency") - .effectiveDate(LocalDate.parse("2019-12-27")) - .unit(Income.Unit.YEARLY) - .build() - ) - .addIncomeHistory( - Income.builder() - .amount(0L) - .currency("currency") - .effectiveDate(LocalDate.parse("2019-12-27")) - .unit(Income.Unit.YEARLY) - .build() - ) - .isActive(true) - .lastName("last_name") - .latestRehireDate("latest_rehire_date") - .location( - Location.builder() - .city("city") - .country("country") - .line1("line1") - .line2("line2") - .postalCode("postal_code") - .state("state") - .name("name") - .sourceId("source_id") - .build() - ) - .manager( - SandboxDirectoryCreateParams.IndividualOrEmployment.Manager - .builder() - .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") - .build() - ) - .middleName("middle_name") - .addPhoneNumber( - SandboxDirectoryCreateParams.IndividualOrEmployment.PhoneNumber - .builder() - .data("data") - .type( - SandboxDirectoryCreateParams.IndividualOrEmployment - .PhoneNumber - .Type - .WORK - ) - .build() - ) - .preferredName("preferred_name") - .residence( - Location.builder() - .city("city") - .country("country") - .line1("line1") - .line2("line2") - .postalCode("postal_code") - .state("state") - .name("name") - .sourceId("source_id") - .build() - ) - .sourceId("source_id") - .ssn("ssn") - .startDate("start_date") - .title("title") - .build() - ) - .build() + listOf( + SandboxDirectoryCreateParams.IndividualOrEmployment.builder() + .classCode("class_code") + .addCustomField( + SandboxDirectoryCreateParams.IndividualOrEmployment.CustomField + .builder() + .name("name") + .value(JsonValue.from(mapOf())) + .build() + ) + .department( + SandboxDirectoryCreateParams.IndividualOrEmployment.Department.builder() + .name("name") + .build() + ) + .dob("dob") + .addEmail( + SandboxDirectoryCreateParams.IndividualOrEmployment.Email.builder() + .data("data") + .type( + SandboxDirectoryCreateParams.IndividualOrEmployment.Email.Type + .WORK + ) + .build() + ) + .employment( + SandboxDirectoryCreateParams.IndividualOrEmployment.Employment.builder() + .subtype( + SandboxDirectoryCreateParams.IndividualOrEmployment.Employment + .Subtype + .FULL_TIME + ) + .type( + SandboxDirectoryCreateParams.IndividualOrEmployment.Employment + .Type + .EMPLOYEE + ) + .build() + ) + .employmentStatus( + SandboxDirectoryCreateParams.IndividualOrEmployment.EmploymentStatus + .ACTIVE + ) + .encryptedSsn("encrypted_ssn") + .endDate("end_date") + .ethnicity( + SandboxDirectoryCreateParams.IndividualOrEmployment.Ethnicity.ASIAN + ) + .firstName("first_name") + .flsaStatus( + SandboxDirectoryCreateParams.IndividualOrEmployment.FlsaStatus.EXEMPT + ) + .gender(SandboxDirectoryCreateParams.IndividualOrEmployment.Gender.FEMALE) + .income( + Income.builder() + .amount(0L) + .currency("currency") + .effectiveDate(LocalDate.parse("2019-12-27")) + .unit(Income.Unit.YEARLY) + .build() + ) + .addIncomeHistory( + Income.builder() + .amount(0L) + .currency("currency") + .effectiveDate(LocalDate.parse("2019-12-27")) + .unit(Income.Unit.YEARLY) + .build() + ) + .isActive(true) + .lastName("last_name") + .latestRehireDate("latest_rehire_date") + .location( + Location.builder() + .city("city") + .country("country") + .line1("line1") + .line2("line2") + .postalCode("postal_code") + .state("state") + .name("name") + .sourceId("source_id") + .build() + ) + .manager( + SandboxDirectoryCreateParams.IndividualOrEmployment.Manager.builder() + .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") + .build() + ) + .middleName("middle_name") + .addPhoneNumber( + SandboxDirectoryCreateParams.IndividualOrEmployment.PhoneNumber + .builder() + .data("data") + .type( + SandboxDirectoryCreateParams.IndividualOrEmployment.PhoneNumber + .Type + .WORK + ) + .build() + ) + .preferredName("preferred_name") + .residence( + Location.builder() + .city("city") + .country("country") + .line1("line1") + .line2("line2") + .postalCode("postal_code") + .state("state") + .name("name") + .sourceId("source_id") + .build() + ) + .sourceId("source_id") + .ssn("ssn") + .startDate("start_date") + .title("title") + .build() + ) ) directories.forEach { it.validate() } diff --git a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceTest.kt b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceTest.kt index 235b740cb..33c4963df 100644 --- a/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceTest.kt +++ b/finch-java-core/src/test/kotlin/com/tryfinch/api/services/blocking/sandbox/EmploymentServiceTest.kt @@ -47,6 +47,7 @@ internal class EmploymentServiceTest { .employmentStatus(SandboxEmploymentUpdateParams.EmploymentStatus.ACTIVE) .endDate("end_date") .firstName("first_name") + .flsaStatus(SandboxEmploymentUpdateParams.FlsaStatus.EXEMPT) .income( Income.builder() .amount(0L) diff --git a/finch-java-proguard-test/build.gradle.kts b/finch-java-proguard-test/build.gradle.kts index 8e17499d4..b4fec9ae3 100644 --- a/finch-java-proguard-test/build.gradle.kts +++ b/finch-java-proguard-test/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { testImplementation(project(":finch-java")) testImplementation(kotlin("test")) testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } diff --git a/finch-java-proguard-test/src/test/kotlin/com/tryfinch/api/proguard/ProGuardCompatibilityTest.kt b/finch-java-proguard-test/src/test/kotlin/com/tryfinch/api/proguard/ProGuardCompatibilityTest.kt index 3a0a0cafc..cf2bc8327 100644 --- a/finch-java-proguard-test/src/test/kotlin/com/tryfinch/api/proguard/ProGuardCompatibilityTest.kt +++ b/finch-java-proguard-test/src/test/kotlin/com/tryfinch/api/proguard/ProGuardCompatibilityTest.kt @@ -93,19 +93,19 @@ internal class ProGuardCompatibilityTest { fun individualRoundtrip() { val jsonMapper = jsonMapper() val individual = - Individual.ofUnionMember0( - Individual.UnionMember0.builder() + Individual.ofIndividual( + Individual.InnerIndividual.builder() .id("182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e") .dob("dob") - .ethnicity(Individual.UnionMember0.Ethnicity.ASIAN) + .ethnicity(Individual.InnerIndividual.Ethnicity.ASIAN) .firstName("first_name") - .gender(Individual.UnionMember0.Gender.FEMALE) + .gender(Individual.InnerIndividual.Gender.FEMALE) .lastName("last_name") .middleName("middle_name") .addPhoneNumber( - Individual.UnionMember0.PhoneNumber.builder() + Individual.InnerIndividual.PhoneNumber.builder() .data("data") - .type(Individual.UnionMember0.PhoneNumber.Type.WORK) + .type(Individual.InnerIndividual.PhoneNumber.Type.WORK) .build() ) .preferredName("preferred_name") @@ -122,9 +122,9 @@ internal class ProGuardCompatibilityTest { .build() ) .addEmail( - Individual.UnionMember0.Email.builder() + Individual.InnerIndividual.Email.builder() .data("data") - .type(Individual.UnionMember0.Email.Type.WORK) + .type(Individual.InnerIndividual.Email.Type.WORK) .build() ) .encryptedSsn("encrypted_ssn") diff --git a/scripts/build b/scripts/build index f40634826..16a2b00db 100755 --- a/scripts/build +++ b/scripts/build @@ -5,4 +5,4 @@ set -e cd "$(dirname "$0")/.." echo "==> Building classes" -./gradlew build testClasses -x test +./gradlew build testClasses "$@" -x test diff --git a/scripts/fast-format b/scripts/fast-format index 1b3bc473a..35a1dee25 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -24,8 +24,8 @@ if [ ! -f "$FILE_LIST" ]; then exit 1 fi -if ! command -v ktfmt-fast-format &> /dev/null; then - echo "Error: ktfmt-fast-format not found" +if ! command -v ktfmt &> /dev/null; then + echo "Error: ktfmt not found" exit 1 fi @@ -36,7 +36,7 @@ echo "==> Done looking for Kotlin files" if [[ -n "$kt_files" ]]; then echo "==> will format Kotlin files" - echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt-fast-format --kotlinlang-style "$@" + echo "$kt_files" | tr '\n' '\0' | xargs -0 ktfmt --kotlinlang-style "$@" else echo "No Kotlin files to format -- expected outcome during incremental formatting" fi diff --git a/scripts/mock b/scripts/mock index 0b28f6ea2..04d29019f 100755 --- a/scripts/mock +++ b/scripts/mock @@ -19,23 +19,34 @@ fi echo "==> Starting mock server with URL ${URL}" -# Run prism mock on the given spec +# Run steady mock on the given spec if [ "$1" == "--daemon" ]; then - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + # Pre-install the package so the download doesn't eat into the startup timeout + npm exec --package=@stdy/cli@0.22.1 -- steady --version - # Wait for server to come online + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=brackets --validator-form-array-format=brackets --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" &> .stdy.log & + + # Wait for server to come online via health endpoint (max 30s) echo -n "Waiting for server" - while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + attempts=0 + while ! curl --silent --fail "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1; do + if ! kill -0 $! 2>/dev/null; then + echo + cat .stdy.log + exit 1 + fi + attempts=$((attempts + 1)) + if [ "$attempts" -ge 300 ]; then + echo + echo "Timed out waiting for Steady server to start" + cat .stdy.log + exit 1 + fi echo -n "." sleep 0.1 done - if grep -q "✖ fatal" ".prism.log"; then - cat .prism.log - exit 1 - fi - echo else - npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" + npm exec --package=@stdy/cli@0.22.1 -- steady --host 127.0.0.1 -p 4010 --validator-query-array-format=brackets --validator-form-array-format=brackets --validator-query-object-format=brackets --validator-form-object-format=brackets "$URL" fi diff --git a/scripts/test b/scripts/test index 047bc1dbb..e81baf829 100755 --- a/scripts/test +++ b/scripts/test @@ -9,8 +9,8 @@ GREEN='\033[0;32m' YELLOW='\033[0;33m' NC='\033[0m' # No Color -function prism_is_running() { - curl --silent "http://localhost:4010" >/dev/null 2>&1 +function steady_is_running() { + curl --silent "http://127.0.0.1:4010/_x-steady/health" >/dev/null 2>&1 } kill_server_on_port() { @@ -25,7 +25,7 @@ function is_overriding_api_base_url() { [ -n "$TEST_API_BASE_URL" ] } -if ! is_overriding_api_base_url && ! prism_is_running ; then +if ! is_overriding_api_base_url && ! steady_is_running ; then # When we exit this script, make sure to kill the background mock server process trap 'kill_server_on_port 4010' EXIT @@ -36,19 +36,19 @@ fi if is_overriding_api_base_url ; then echo -e "${GREEN}✔ Running tests against ${TEST_API_BASE_URL}${NC}" echo -elif ! prism_is_running ; then - echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Prism server" +elif ! steady_is_running ; then + echo -e "${RED}ERROR:${NC} The test suite will not run without a mock Steady server" echo -e "running against your OpenAPI spec." echo echo -e "To run the server, pass in the path or url of your OpenAPI" - echo -e "spec to the prism command:" + echo -e "spec to the steady command:" echo - echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo -e " \$ ${YELLOW}npm exec --package=@stdy/cli@0.22.1 -- steady path/to/your.openapi.yml --host 127.0.0.1 -p 4010 --validator-query-array-format=brackets --validator-form-array-format=brackets --validator-query-object-format=brackets --validator-form-object-format=brackets${NC}" echo exit 1 else - echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo -e "${GREEN}✔ Mock steady server is running with your OpenAPI spec${NC}" echo fi