From db34c4af675d9c7245525201b1da9b6c84a50433 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 15:29:27 +0000 Subject: [PATCH 01/24] chore: sync repo --- .devcontainer/Dockerfile | 23 + .devcontainer/devcontainer.json | 20 + .github/workflows/ci.yml | 85 +++ .github/workflows/publish-sonatype.yml | 41 + .github/workflows/release-doctor.yml | 24 + .gitignore | 357 +-------- .release-please-manifest.json | 3 + .stats.yml | 4 + Demo/GetTrustedInstallerShell.mp4 | Bin 827724 -> 0 bytes GetTrustedInstallerShell.sln | 31 - .../GetTrustedInstallerShell.vcxproj | 148 ---- .../GetTrustedInstallerShell.vcxproj.filters | 22 - GetTrustedInstallerShell/src/main.cpp | 304 -------- LICENSE | 222 +++++- README.md | 589 ++++++++++++++- SECURITY.md | 23 + bin/check-release-environment | 33 + build.gradle.kts | 49 ++ buildSrc/build.gradle.kts | 12 + .../pioneer-intergration-app.java.gradle.kts | 136 ++++ ...pioneer-intergration-app.kotlin.gradle.kts | 106 +++ ...ioneer-intergration-app.publish.gradle.kts | 60 ++ gradle.properties | 18 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43583 bytes gradle/wrapper/gradle-wrapper.properties | 7 + gradlew | 251 +++++++ gradlew.bat | 94 +++ .../build.gradle.kts | 15 + .../api/client/okhttp/OkHttpClient.kt | 254 +++++++ .../PioneerIntergrationAppOkHttpClient.kt | 289 ++++++++ ...PioneerIntergrationAppOkHttpClientAsync.kt | 290 ++++++++ .../build.gradle.kts | 42 ++ .../client/PioneerIntergrationAppClient.kt | 86 +++ .../PioneerIntergrationAppClientAsync.kt | 86 +++ .../PioneerIntergrationAppClientAsyncImpl.kt | 88 +++ .../PioneerIntergrationAppClientImpl.kt | 85 +++ .../api/core/BaseDeserializer.kt | 44 ++ .../api/core/BaseSerializer.kt | 6 + .../api/core/Check.kt | 86 +++ .../api/core/ClientOptions.kt | 446 +++++++++++ .../api/core/DefaultSleeper.kt | 14 + .../api/core/ObjectMappers.kt | 167 +++++ .../api/core/Params.kt | 16 + .../api/core/PhantomReachable.kt | 54 ++ .../core/PhantomReachableExecutorService.kt | 58 ++ .../api/core/PhantomReachableSleeper.kt | 21 + .../api/core/PrepareRequest.kt | 16 + .../api/core/Properties.kt | 42 ++ .../api/core/RequestOptions.kt | 45 ++ .../api/core/Sleeper.kt | 17 + .../api/core/Timeout.kt | 155 ++++ .../api/core/Utils.kt | 102 +++ .../api/core/Values.kt | 700 ++++++++++++++++++ .../api/core/handlers/EmptyHandler.kt | 12 + .../api/core/handlers/ErrorHandler.kt | 80 ++ .../api/core/handlers/JsonHandler.kt | 20 + .../api/core/handlers/StringHandler.kt | 13 + .../api/core/http/Headers.kt | 111 +++ .../api/core/http/HttpClient.kt | 17 + .../api/core/http/HttpMethod.kt | 13 + .../api/core/http/HttpRequest.kt | 175 +++++ .../api/core/http/HttpRequestBodies.kt | 125 ++++ .../api/core/http/HttpRequestBody.kt | 22 + .../api/core/http/HttpResponse.kt | 19 + .../api/core/http/HttpResponseFor.kt | 24 + .../http/PhantomReachableClosingHttpClient.kt | 25 + .../PhantomReachableClosingStreamResponse.kt | 20 + .../api/core/http/QueryParams.kt | 125 ++++ .../api/core/http/RetryingHttpClient.kt | 248 +++++++ .../api/core/http/StreamResponse.kt | 13 + .../api/errors/BadRequestException.kt | 74 ++ .../api/errors/InternalServerException.kt | 85 +++ .../api/errors/NotFoundException.kt | 70 ++ .../api/errors/PermissionDeniedException.kt | 74 ++ .../errors/PioneerIntergrationAppException.kt | 4 + ...neerIntergrationAppInvalidDataException.kt | 6 + .../PioneerIntergrationAppIoException.kt | 4 + ...ioneerIntergrationAppRetryableException.kt | 14 + .../PioneerIntergrationAppServiceException.kt | 17 + .../api/errors/RateLimitException.kt | 74 ++ .../api/errors/UnauthorizedException.kt | 74 ++ .../errors/UnexpectedStatusCodeException.kt | 86 +++ .../errors/UnprocessableEntityException.kt | 74 ++ .../api/models/Order.kt | 454 ++++++++++++ .../api/models/pets/Category.kt | 180 +++++ .../api/models/pets/Pet.kt | 663 +++++++++++++++++ .../api/models/pets/PetCreateParams.kt | 199 +++++ .../api/models/pets/PetDeleteParams.kt | 229 ++++++ .../api/models/pets/PetFindByStatusParams.kt | 322 ++++++++ .../api/models/pets/PetFindByTagsParams.kt | 197 +++++ .../api/models/pets/PetRetrieveParams.kt | 190 +++++ .../api/models/pets/PetUpdateByIdParams.kt | 265 +++++++ .../api/models/pets/PetUpdateParams.kt | 199 +++++ .../api/models/pets/PetUploadImageParams.kt | 225 ++++++ .../api/models/pets/PetUploadImageResponse.kt | 212 ++++++ .../models/store/StoreListInventoryParams.kt | 169 +++++ .../store/StoreListInventoryResponse.kt | 112 +++ .../models/store/orders/OrderCreateParams.kt | 185 +++++ .../models/store/orders/OrderDeleteParams.kt | 232 ++++++ .../store/orders/OrderRetrieveParams.kt | 193 +++++ .../api/models/users/User.kt | 388 ++++++++++ .../api/models/users/UserCreateParams.kt | 184 +++++ .../models/users/UserCreateWithListParams.kt | 191 +++++ .../api/models/users/UserDeleteParams.kt | 222 ++++++ .../api/models/users/UserLoginParams.kt | 202 +++++ .../api/models/users/UserLogoutParams.kt | 169 +++++ .../api/models/users/UserRetrieveParams.kt | 183 +++++ .../api/models/users/UserUpdateParams.kt | 206 ++++++ .../api/services/async/PetServiceAsync.kt | 323 ++++++++ .../api/services/async/PetServiceAsyncImpl.kt | 316 ++++++++ .../api/services/async/StoreServiceAsync.kt | 70 ++ .../services/async/StoreServiceAsyncImpl.kt | 91 +++ .../api/services/async/UserServiceAsync.kt | 279 +++++++ .../services/async/UserServiceAsyncImpl.kt | 264 +++++++ .../services/async/store/OrderServiceAsync.kt | 169 +++++ .../async/store/OrderServiceAsyncImpl.kt | 146 ++++ .../api/services/blocking/PetService.kt | 314 ++++++++ .../api/services/blocking/PetServiceImpl.kt | 310 ++++++++ .../api/services/blocking/StoreService.kt | 68 ++ .../api/services/blocking/StoreServiceImpl.kt | 89 +++ .../api/services/blocking/UserService.kt | 270 +++++++ .../api/services/blocking/UserServiceImpl.kt | 258 +++++++ .../services/blocking/store/OrderService.kt | 160 ++++ .../blocking/store/OrderServiceImpl.kt | 141 ++++ .../pioneer-intergration-app-kotlin-core.pro | 32 + .../api/TestServerExtension.kt | 62 ++ .../api/core/ClientOptionsTest.kt | 34 + .../api/core/ObjectMappersTest.kt | 102 +++ .../api/core/PhantomReachableTest.kt | 27 + .../api/core/UtilsTest.kt | 33 + .../api/core/ValuesTest.kt | 127 ++++ .../api/core/http/HeadersTest.kt | 242 ++++++ .../api/core/http/HttpRequestTest.kt | 110 +++ .../api/core/http/QueryParamsTest.kt | 180 +++++ .../api/core/http/RetryingHttpClientTest.kt | 353 +++++++++ .../api/models/OrderTest.kt | 51 ++ .../api/models/pets/CategoryTest.kt | 33 + .../api/models/pets/PetCreateParamsTest.kt | 68 ++ .../api/models/pets/PetDeleteParamsTest.kt | 23 + .../models/pets/PetFindByStatusParamsTest.kt | 34 + .../models/pets/PetFindByTagsParamsTest.kt | 36 + .../api/models/pets/PetRetrieveParamsTest.kt | 23 + .../api/models/pets/PetTest.kt | 50 ++ .../models/pets/PetUpdateByIdParamsTest.kt | 43 ++ .../api/models/pets/PetUpdateParamsTest.kt | 68 ++ .../models/pets/PetUploadImageParamsTest.kt | 77 ++ .../models/pets/PetUploadImageResponseTest.kt | 36 + .../store/StoreListInventoryParamsTest.kt | 13 + .../store/StoreListInventoryResponseTest.kt | 37 + .../store/orders/OrderCreateParamsTest.kt | 65 ++ .../store/orders/OrderDeleteParamsTest.kt | 23 + .../store/orders/OrderRetrieveParamsTest.kt | 23 + .../api/models/users/UserCreateParamsTest.kt | 69 ++ .../users/UserCreateWithListParamsTest.kt | 69 ++ .../api/models/users/UserDeleteParamsTest.kt | 23 + .../api/models/users/UserLoginParamsTest.kt | 39 + .../api/models/users/UserLogoutParamsTest.kt | 13 + .../models/users/UserRetrieveParamsTest.kt | 23 + .../api/models/users/UserTest.kt | 56 ++ .../api/models/users/UserUpdateParamsTest.kt | 80 ++ .../api/services/ErrorHandlingTest.kt | 349 +++++++++ .../api/services/ServiceParamsTest.kt | 84 +++ .../api/services/async/PetServiceAsyncTest.kt | 170 +++++ .../services/async/StoreServiceAsyncTest.kt | 28 + .../services/async/UserServiceAsyncTest.kt | 160 ++++ .../async/store/OrderServiceAsyncTest.kt | 68 ++ .../api/services/blocking/PetServiceTest.kt | 169 +++++ .../api/services/blocking/StoreServiceTest.kt | 28 + .../api/services/blocking/UserServiceTest.kt | 160 ++++ .../blocking/store/OrderServiceTest.kt | 68 ++ .../build.gradle.kts | 19 + pioneer-intergration-app-kotlin-lib/.keep | 4 + .../build.gradle.kts | 101 +++ .../api/proguard/ProGuardCompatibilityTest.kt | 76 ++ .../test.pro | 9 + .../build.gradle.kts | 29 + release-please-config.json | 67 ++ scripts/build | 8 + scripts/format | 13 + scripts/lint | 13 + scripts/mock | 41 + scripts/test | 56 ++ settings.gradle.kts | 14 + 183 files changed, 20075 insertions(+), 879 deletions(-) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/publish-sonatype.yml create mode 100644 .github/workflows/release-doctor.yml create mode 100644 .release-please-manifest.json create mode 100644 .stats.yml delete mode 100644 Demo/GetTrustedInstallerShell.mp4 delete mode 100644 GetTrustedInstallerShell.sln delete mode 100644 GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj delete mode 100644 GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj.filters delete mode 100644 GetTrustedInstallerShell/src/main.cpp create mode 100644 SECURITY.md create mode 100644 bin/check-release-environment create mode 100644 build.gradle.kts create mode 100644 buildSrc/build.gradle.kts create mode 100644 buildSrc/src/main/kotlin/pioneer-intergration-app.java.gradle.kts create mode 100644 buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts create mode 100644 buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts create mode 100644 pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt create mode 100644 pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt create mode 100644 pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt create mode 100644 pioneer-intergration-app-kotlin-core/build.gradle.kts create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseDeserializer.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseSerializer.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Check.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/DefaultSleeper.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Params.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachable.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableExecutorService.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableSleeper.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PrepareRequest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Properties.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/RequestOptions.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Sleeper.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Timeout.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Utils.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/EmptyHandler.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/ErrorHandler.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/JsonHandler.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/StringHandler.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/Headers.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpMethod.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBodies.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBody.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponse.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponseFor.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingHttpClient.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingStreamResponse.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/QueryParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/StreamResponse.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/Order.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Category.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Pet.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponse.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponse.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/User.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParams.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsync.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsync.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsync.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsync.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetService.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreService.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserService.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderService.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceImpl.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/TestServerExtension.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ClientOptionsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/UtilsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ValuesTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HeadersTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/QueryParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClientTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/OrderTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/CategoryTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponseTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponseTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ErrorHandlingTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceTest.kt create mode 100644 pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceTest.kt create mode 100644 pioneer-intergration-app-kotlin-example/build.gradle.kts create mode 100644 pioneer-intergration-app-kotlin-lib/.keep create mode 100644 pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts create mode 100644 pioneer-intergration-app-kotlin-proguard-test/src/test/kotlin/com/pioneer_intergration_app/api/proguard/ProGuardCompatibilityTest.kt create mode 100644 pioneer-intergration-app-kotlin-proguard-test/test.pro create mode 100644 pioneer-intergration-app-kotlin/build.gradle.kts create mode 100644 release-please-config.json create mode 100755 scripts/build create mode 100755 scripts/format create mode 100755 scripts/lint create mode 100755 scripts/mock create mode 100755 scripts/test create mode 100644 settings.gradle.kts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..bd8e261 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,23 @@ +# syntax=docker/dockerfile:1 +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libxkbcommon0 \ + ca-certificates \ + ca-certificates-java \ + make \ + curl \ + git \ + openjdk-17-jdk-headless \ + unzip \ + libc++1 \ + vim \ + && apt-get clean autoclean + +# Ensure UTF-8 encoding +ENV LANG=C.UTF-8 +ENV LC_ALL=C.UTF-8 + +WORKDIR /workspace + +COPY . /workspace diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..d55fc4d --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,20 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Debian", + "build": { + "dockerfile": "Dockerfile" + } + + // Features to add to the dev container. More info: https://containers.dev/features. + // "features": {}, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], + + // Configure tool-specific properties. + // "customizations": {}, + + // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. + // "remoteUser": "root" +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ae73a9a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,85 @@ +name: CI +on: + push: + branches-ignore: + - 'generated' + - 'codegen/**' + - 'integrated/**' + - 'stl-preview-head/**' + - 'stl-preview-base/**' + pull_request: + branches-ignore: + - 'stl-preview-head/**' + - 'stl-preview-base/**' + +jobs: + lint: + timeout-minutes: 15 + name: lint + runs-on: ${{ github.repository == 'stainless-sdks/pioneer-intergration-app-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + + steps: + - uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Run lints + run: ./scripts/lint + + build: + timeout-minutes: 15 + name: build + runs-on: ${{ github.repository == 'stainless-sdks/pioneer-intergration-app-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + + steps: + - uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build SDK + run: ./scripts/build + + test: + timeout-minutes: 15 + name: test + runs-on: ${{ github.repository == 'stainless-sdks/pioneer-intergration-app-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} + if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + steps: + - uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/gradle-build-action@v2 + + - name: Run tests + run: ./scripts/test diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml new file mode 100644 index 0000000..0d6e20f --- /dev/null +++ b/.github/workflows/publish-sonatype.yml @@ -0,0 +1,41 @@ +# This workflow is triggered when a GitHub release is created. +# It can also be run manually to re-publish to Sonatype in case it failed for some reason. +# You can run this workflow by navigating to https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell/actions/workflows/publish-sonatype.yml +name: Publish Sonatype +on: + workflow_dispatch: + + release: + types: [published] + +jobs: + publish: + name: publish + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: | + 8 + 21 + cache: gradle + + - name: Set up Gradle + uses: gradle/gradle-build-action@v2 + + - name: Publish to Sonatype + run: |- + export -- GPG_SIGNING_KEY_ID + printenv -- GPG_SIGNING_KEY | gpg --batch --passphrase-fd 3 --import 3<<< "$GPG_SIGNING_PASSWORD" + GPG_SIGNING_KEY_ID="$(gpg --with-colons --list-keys | awk -F : -- '/^pub:/ { getline; print "0x" substr($10, length($10) - 7) }')" + ./gradlew publish --no-configuration-cache + env: + SONATYPE_USERNAME: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }} + GPG_SIGNING_KEY: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_KEY || secrets.GPG_SIGNING_KEY }} + GPG_SIGNING_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_PASSWORD || secrets.GPG_SIGNING_PASSWORD }} \ No newline at end of file diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml new file mode 100644 index 0000000..f7ff40c --- /dev/null +++ b/.github/workflows/release-doctor.yml @@ -0,0 +1,24 @@ +name: Release Doctor +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + release_doctor: + name: release doctor + runs-on: ubuntu-latest + if: github.repository == 'ummitsmerogers-droid/GetTrustedInstallerShell' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') + + steps: + - uses: actions/checkout@v4 + + - name: Check release environment + run: | + bash ./bin/check-release-environment + env: + SONATYPE_USERNAME: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }} + GPG_SIGNING_KEY: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_KEY || secrets.GPG_SIGNING_KEY }} + GPG_SIGNING_PASSWORD: ${{ secrets.PIONEER_INTERGRATION_APP_SONATYPE_GPG_SIGNING_PASSWORD || secrets.GPG_SIGNING_PASSWORD }} diff --git a/.gitignore b/.gitignore index dfcfd56..b1346e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,350 +1,7 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ +.prism.log +.gradle +.idea +.kotlin +build/ +codegen.log +kls_database.db diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..1332969 --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "0.0.1" +} \ No newline at end of file diff --git a/.stats.yml b/.stats.yml new file mode 100644 index 0000000..c040c03 --- /dev/null +++ b/.stats.yml @@ -0,0 +1,4 @@ +configured_endpoints: 19 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml +openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 +config_hash: 6d70aedc8c7eb71038c9cebef29eb95d diff --git a/Demo/GetTrustedInstallerShell.mp4 b/Demo/GetTrustedInstallerShell.mp4 deleted file mode 100644 index ed9b3b2ff3a29a56bee08ad8a21f953c95d07ff0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 827724 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
~}}` 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

?Z+Gs?%-nz5f*2n?? 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

E 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 *Xin79@`OBWCAsi zkDC|98E=a}NWXt&g^FGLvw3UUXbrD$o!gs6%UKy}o58T6ou7%`QaI$L51_7(AdPc! zf?C1rm>m&x`|2Mn!>L4ezz8c=B}^cj6zJ?RwjzbhJCtRfYZi`-g8I1?T1Xubx)+9A z2xys`&j_Q8(CIGUho_uxAGUs-vcU7U^E*XxXF}UT2U79&VFy`tGLKC!a$P_(e7B0~ z0?3z$oAXR^<5!>7G*GK=56*4#IbmWxjA1ykq3O)%-aKW(BEPCAELs1QJG#VTsMTbF zHp4T~iBUa)J2AZ!(iLOxs5lvDX6m(`LQ(_g%ts{M2>~a>A@_~)e2&wV9gX%ZjZ=

nskAx?l&F%CzXaCwSYQW7a zSz?>X8@w=1SdkD6%^Gnl6+hWIeo|9E!gd@`1i24BPSL#(0IcnNd^N#BE$r^k(NnE8 zc^!`>a`-cJpO7BNjw`TX6$`d~6enrZoj>4H(QP8S_*f2WGB%*UoCZI{Z|BQ37wtd? z_8Kk+LCz1C^WUX#M8_g32{)mC_0LVcbi_oSONCw=-%8@cA06ro2`{NBG;cO*g;K7u zZGCOgXFDm#;6E6BY$+A8efbj}8rE7?m1o9w<}sg@^au#+_(?z_lwfc9p4p+a_m;yI zSkIQ}nYV_PoL8^34=%}8n=Qg<9~4Uo?lYr7OYgT*$Yn4|=|r~<9+~<<1~v{-m(k2g zkk80w>;WEz3)FWS)sl*3Tg4b!7-TGU-*t@fRI zOMf);GlUZ?+o29xBK`R{(E|4PFQNr_kRXHp-;0*H7d-7n%HJ`0wOjBJNn6k(?H=hJ zuOp>BQAR}Z({MS!8bo`&O4I-VV5FBf$$+uiilYiz-InqIOMyJs34qU*cB1roQ$Ro~ z`tTn9t`Q`>v?d}JQu*5AqtVAcPtm~9-zdppL9}3Z7kWSK?%$3OJ^0f*txkF)MGWy> z{5#{+h7Z(gFV~q|S_dd04wD#6&A{OOqgKWNNLl>P-X7<8@ut$ZRptvYP@p5O$&NWc zs~KO2N5+Y+9*(VV{ogS4LStQ}jD})Gncz1~xyK2}xM9}TP7v+ua5fG_tKX$P*!}J0 zxp~g*v~mu)?XT^DdGeW_jfvq|kn%6eqNGdo-!EI?z-7{b-NW`c=<<1!f?jaWUa_kT zN8G_l45Dz?BV+Lt- z9sgo_uLVzBX$eN#F>c^2(CBb2>W8iUaeL5Z4zRVx_e7xbe(eWpMQ!c&%p2htvW@7u zbss6sJDl>|sNf>PVQcNR40dii<9#imOh#rzm-6bQ*xGvaJ4MnJd}rBU{SYDdX&`_N zY`Z9xB?rWjQYRuy!zP|oj2J%Gj)!Wzt z#Jg`yWf#7t0R_8tU` zKKnwz8T5xdCWr#baA9Bg=}>8F4QwDIj{q~k8q{C!^nV-D2hskQ)67>%kiqyroMwWY z5)e#*bKZWr80<#!aI!+T_@yZAe8QksSYpO5E_b=K15%Ua!EN<-vfoCedK_*`WTzz4 z8U5V}ajR2o7T?)?lNE7U5~wJdTVmM|)*NlaO9e306%2}iC;%y5EdrS*KWW;Mz%|W!hzBDM4On9sv znS5gR@gm+3e)fP6%zQOZLrrXTT!qX!nU;O5*+(7Gpeux;7Uc?XiYFH@%1zB2LYspt zj!`;}+Sx;8zpT_5p~^FhTH>12T|>Rs%U&Q2O-ukz?c^7oy6v?p7cxDgT532WBR^cN z9V#}hUe2f6aAqlW)-MVc{&5xt2#T0KGrm*a9A1H(L!CRM<#3;$51NDYL@aF)aq$-i z;Lh1kvr0a4`32B4o--ZtowyLFCDV4I6KRM4B=qtJykC&Q*YnThvKE$+&nHY;hR_U+ zBzk;}d0qQ85%?>btdL}sE7i}sB}3W9p$7c=b|R;Zd+rg#l!yUcwNsr}&2(0&q5;f( z>iywK`9l1$Z$LC9l4a{sB`-$RO~w6EKKE0o0$DPJ#t%6AMqbSeqe2uvsZ7c~ z+zJLtodVJ5g~0QFO)CIwHr02eh#Wu~6mSWbI{5PqUsv&8dxhADZ|YOS9FVo1%8ke^ zIfQx*0FXikeFi)w_yJ_wnOko)WS!~cqi)`Qx+kuY{Z+VU7FB9HxO%*y{9m?9-5FAB z>CH}o2uBSFa>^q)*~ran(fH{O@|ZZ2=6k(wb%_V;7G_}?4+_SgnRb}za}TN(IDQ)t z8<2v+SoAng9wl)}`r@E?Rz7t~+CU+v*;rYw>mT!I=V%_()QXHDHoZ1IeaL7IZARak zww}E@xh6~%)+wJ#pF;7j_;Uj*r|H(%iDjI(-)LsJp#;$m8$OJwRvCX^ynsQ6CXqTS zizOnFg{DbEDpq$o6=g#d3XstyKTAG^#KF+^jc8HTE~+TFWyM@1e@uSZ{iC&)t3qq4 zH{7F0XvP6?kIZr38VN-b2r=*4A;_Vv|7CE!{)n^j!| z>B45VnPQHu$kD#d|N6Qqi+ppS@GEiEI=P(OS4XC6hrNu_CGO;t!M;y!@etaUHLH{iCfGqE8@MTlL~g_7 zI+Ld2@fuje8hM!XVg!D~ayedumHMkgMa5s>G-XBmig`yxYu)H$6glM^_zP$!nU|Jri z)<_?UNXR0s)uw{`thK_^*ylkaO*&!TL^*a*;X>82u@N}VQDLs5cm?MD!^%{U`D7Zc zHM%%4C&^L`SG!Nct}_p%nZ-CJ(n9c}8oJj8Q@=P^MFFMF;x4Fk;8#mN)sE;s7Ec4W zgk!8?1u$T(x1k~;5LTkI#GJak)MZ*Jozv9Pmm)2Md#ga58==%z6#57%6LhewrW_Jt zvPI1nXZqVoX644V*#d;l(9C64WaigfJBj!}w+oFzjujcPfbp=Y9<1* zj?p53Nj+llPWCIIvAJG~aBXze`+m@&=g#me-&{?Mz0l%!9O(r&~%YuS2E%zk^8jO7SelnBbbE3>fFa>)mdz0VkW1ZA5oB*fww~^fc@yhQ7X1Vw3`pdwt9&L_uNXrUC1-lygCrJ@uih}JlrZhNod?rvV-@+- zLw~{;CUyon08fE#o69cIsEE$-azbNT=h~a{^z=u`Q7x9KFpzyP*6fxrqE$T4bVML| z?v74YWW>Y9u%_SpmV#o7t#HT)sVrXN`Vix8b zGPOmUK=sP7kiz>+BXD#MN0a${4yivHey|C{Dxa@lXr11XcTyi_I%Qz@48m;GWcfp& zx{_{Eft0;BsWQd{ka*CN*->ZGo&NzaESAB3?Vi(0iF1;WX~}@+7n%)3yQ^q*pp10_ zoC&X172w!X@)SptPPyo_oBZ$_NiI8l!b~Q5u<%3f^ zi8+iKQ}GnXw>0`nfyym_nUxdbq0OI>+PR>F?9^+Rh=P%?Lt1wA01{JT^w z{}gn|r>1^yaN$9~%p$MI*SIt?72WsjOX>pFL=y^l{eZHofR2TDQ10^7)Uz&*+~PHc zc5Mqx54%=q_D%|;vJNz{Whg}M18;cXI6~7z8Pz(FL(J9ECEvIfq8y!=RC}m9snbqtPVW zo(j6ZnJ4VbtcDZK<}*5lntw(hy(bJ}8S9^jKDFO{(z1=H+$_Nw8pUb4Vgg&86gtaa zAunbBIqwf%zAi<_IT$kIVJ5XCI1}ufB6wCsbrP7dQjV=@yLO0hyyg?koMW`^XTUJ` zxOi^#c7Mx7o=Os_iO6t%JT>5GaBW#a{zg9vq3nio*%U8viewq5OFot|vZOm6;~bD_ zqY{gJsN%No(3mOvj9wfx&%Ht+Ui51tt3FQ|)}93u*${!ejmcmf76_5|0Pc5|XJ4bl zMnB$+B9DXNZ1Was2$kVPOkRAkWFzko#Fqk72g4yd|q z7b(rM2hUhi-6;wXt%_*Jo+!!^BV$Jh8SQ;%PrgZo>c>dTpTUb}S|1qw5SJ6RK8U}a zYBwZqU|z_K#qopAP()Zppw;pWfYTm|h`^eR*fSnV1I3<3bQfCs(AsMrtT(zgvm>Um zLK);wDEFQ6A4{&d;h!z+sd?i!Rld2(x#V7UW*HcFT7Z?%NBpoT)15a@#8R64wizx>g@Ie}(!oE&$OirzC@EP>}YJ3y!Tm{^~f0 z@X_+03-0pn!uf$*@sUeb0m#fnM(+-}>wwWbg8+BGOIHuzj;-uq!Y&`IJmZ^mizO3o zw8+)w)2T1>R{*_(@#}}}-Cd2`I+Z*}(;XiaKjUJN1!IYYBrN)ldK7et)d#-U`OI>T zvoRPq0My#@qq%5sno_({k#Yfa_{E7r42I0yQ73zD1P^1JNuhl0%bSwcU4(&=Q8P8~ z2fN?zXF#``wU*zwCW|N^F)xqf8z3*xz?+bquNNz$ zn#A^_=Rq&vo$jgvStzZGGz4Y(Q-_m>3map1*Vf(<=<@feW--fmo*ec10eVQt(0)v+ zRu_;Dr&`?C2CJcd7+}wfS;8SQ_5Z@&JH?6?HQj>Swr$(CZQHhO+qP}nd!KFFHqN&D zBsYI2x6_@Q`{$;gzV%cOE1AhyD^)dWR@Hb>b2li`G^?d`>jVS|x7LjCz(>$}^8n$w zOf*J--2DcooB~^W2Ig$y^d)2oy@ahIIm0qMuOtFZ%a_iyreyi!i|ZX(7ZbBmpD=#p zhA0%*f;;{J!7Mx#`{_8M;1&KQo&S=9ZZjC1$ixyyq1^_u@LSpu`P+;HAvCRTzs3mOKG{LmdoA$`NVkD2LvBQ*6BrVF6cVsX% zmS5_+(WPFY>`=xhrm-LO05Oy$r_d*1>HTc#J#o=I1V*`Q!eDedwtJ`dzSv?x9(+uz zcSlZ^7v*7_HS)E*j1U%SCLSev6JQlzDLaY#f->AYYOqp8TwPNZ2SI#@FG^tdriSBqZ#6c$}#9Nk1dgi(SHZ5j&#A6F?kH0QRXnOBefHRp>r) zau8js_#;Zwa8#EHElxDcwN)_>WlW5=O+{+@AjX2NAO0!A6J{6Ke*w_H)~K*!~?o`ja!2kvAMmQLKgc{8MJa{5_FWxwenTD~JGc-Wg+I9uvg zzgPAxyFf0KBLQW-jY@9#3ms)!)Ox`TrmY{$iudwdy6O>RfJ~WQotXYIyZGq(ZQlf_ zsx2b$fUx^@6`{gqC=8gjyj)P=4`ngrd)NG7>q4r&5Kbem0sPmmQqHYRI0|2WjhoGt z)SRJFtZL6+umCHA-;A$3xI=GRu;H}nAX5F!G6GJ(9~m9)OPHbL;XD76jf4B+#7>AS zSZt}=gM%297zvB>LeJlW;mu=*<0&f9&)kO=$F;<`59TWw_!>}*v}5=nG|CDSa5-yA zuoX=K_*sE6ps4=h)|T)a3p2k(zV$u)3E;*gCBv)3!*`r!;0-GW**bJeFAg`rA+UN_ zYHM*eCP(ZZEci)x#wFU2{BLO(9u+Zz(>9wJ zJbhz~hzptA6F;w^{}2B!oYLvmZc9Il`M_kw#={a~ef+HTJC6|vIR>ZB1%J*osN671LTQ9$p6^9_3>ETeF6Vj}UX`mQ z=^Z2NC#|(YA5=j|^}xi?4A zzzvz;OKBiHfWPipjYVEu_eiGM4#Ik7MI<_~hENI_@KKSkgASEOm>B4&!>e=P3YdlZ z9>ftSpx-CWyJQLLlk{zCHl$oYecZSpS6J1PPbrN1Bg=~iQ}&&YXQDRZYz@IV%1zFU zfO9UySQH=ba&zs&{CIY=+>MKv6<1rY#dZyTIc~wRzI>g8@dm~AAj@0v@?s0@?9GtdS<0w z9E~lzA$PBgPzXzh#q3N=Bg#QH>*Tlt$cls)LhQHyxB_aYU>^DF4Nz)78w-d6BA2_@PcE=B?&S3bZog-x*LUkIu-trHzo=#@uUtD}U4E>t17sVMec`#+^b^`zKXZEiZKzXM;Pi7#74sn>kbJn80EpA&j;sCu>QCQbhDPT~ zKcmuEW3O3P>*#GS!&mX%Wbm8~9+@s3YKtTVA9>ah9&S^&i!Z>BDLQd%Ly{lqhaivg z&sP~;1VxPjoqgB5H^5Z z!p-%xqQ^2RIpJjaIbX|3SZJuwotG$Ow#Qu`^>aT7yEZ3xB{gcwIZ*f{LCkI-5RguN0x8+{YE&k1Y;)+BBP@KQ6^AKm*Uo7iv5t z=W)J>iXgj~NO)Rc)vV9aUxKyv!D_S+WdJ>ik4uei;>r$6J!$+(yo5IXAUHZiktB9Ul<6OgiHF>13M#MpPrho*^-8xxm zN1sq{JgpXbd2q?NJ2nj(o!kziFXm6|6$>Qeg@3t)=$RXVe8~SvbugH6YgrF3+Q2|r zvB!FxqF!%P2fYW43sK5)hbkXMks|lyP#eAyh1l~vNXd%ez`CutCsWl2jTRSTICakP z$OuxPr~r)e8TwcohsJ0>3)=rs)b}sq_PcN7@+4Okzja?D%_2p0$KJcMbHqmQ$RqFr zA;qv~A`@TE8hp3$#p1e*dxWNaLG;er%c48(IS8Fn+JmDN^C3L@lNd9^4aQ^ebo(Y- z%@IFhUi%j1U~S9>VloOaiWcMxmLl`$3^5E3K6|w5Ep(F<7KkGnGFLgV`@qS#f|F6Q zM|Oi%K2F~_3yX?>9L=G!!VNr4YhVHz#&F+(>l1!c9SnJA&AAtqL0HMAdWYE9atVEz zplW_F^7B~H&(|aW3`>s~n@+Bto0ZI~NLb=!>miM~m?jqF(kDCXz-;AyW3HO#3xRCr zTIbOTof*O^C!*(H)KyO*ZfbOCXm1pAYrHJ?JI%J~U15AsoE8t$jqg;N0H2&V?4iUW ziQ1;Yho%=J)5)OPZjHHmjF(Ej2ru|pKpl}|o@;GmAbplB0gjPrro^CViR@oq+;n%C zL8fx6m?yC~l+*%H42zn460a)4&0vfVR2xMDOdW;xa$9#w9qzwz1C&gyn;=;`H3P=g zTv>&MLANr*MA-Pr;}sD?AG||+QsIRr2ccy?t;YQ)RsduxRoyC8@zoLcYGrtX*buC1 z5{jca(r?fe(5#XO-9Ej%l#or4pB8YOmYVnXi&%JCs*WP19m!(j;>WKEnffPU-A~QT zc!>-lfyo?ieVTH?S=-1stA78Hzo&fJG*r41jRDYlt)Pm@_=RPAq4HmMrBruN=r;Be zR^e?uIStTskz9m7*@h_YU$;?m@^Rmz>QZw>{N|EFNPRR?NYYeX^Lmt1dPfWN>c= zokT3_zj(B_V7?{rDV_};?pnKmpBB{oxbop}MNvC7mPsHX_Vv0#CQGoiV_LzpG&C~f zxOJ7eFV~FlrDjTg@tzmr0+Z`ndngi_(q>@Xrcq3sCjAt}Z^i+rd8{RCW1n_* zv2e#G7UcFp-pm|&#|L<}^1V84buUCmpKhi)U=|6{)xEC-Z6HA5(~TpmAEENAi2^G| zl=}r+JA_x#y20ym4D07E1{25zG~UwRJ<=fMWUtU@ACOmSw*^jI6;-i$$zm#2mp`YC z-E&GpM2fvE2Pgm&zqQw)tGlZyGJM}BN+!+-#tNWEb4ZqejrHM^9J8EnxAU>e6Y z{9hK6j4u0&{{#xA>8~<128S@|OFw=J3kURHPRsO*?4JUl72a@>1J;O9z&vn4p5F@_ z{{n&Hb!!?S29htvqtoWeZCack++Qww&T$;&u)mFAA-c?>FFl`+p&+xgGJXxs;4k(Y zaXMJ!dl+-gN)Unhu{uXNWI@~$H?m58%yA14+aZ~kBE;51^m@Vqn7mWBTTmypdI*>A zy5o2z-KyUSrSqw$=~a^zj8a)@9C`LigVExEt=E1Bmapn+U$NC%AB^u1NNv|T@CvH& zM}?`8Ybc=1=ulFwhQ|&hvy5>-XW39D>LCTNvp1bwAKCc!X^EJ9C#FKH_j{1JV2?R8 zd${Q)mPVXr&i1MUxU?8q#!gYK(+6n_gJ}syV+8k*fvI#bXW3PxaZj3^*4(hkP^SsO zlpH^1i;{Z4pF`1loQ#sQS^76r83S61S@n+`0+|O5hVKBgKNc#Hap{Tj5}U4PCml`k z_o`^ZUWk}fV=e4*^j#npzKr8D;qWmKZsLuH5%hW}vpb_O41voP#T!d!8|YsfY1Q&* z3<6&-W!7Bco_QKbCJa3~iPM=kDn1Tcvqsti=O~Y(ue?=gOaE+$(|0y($XR4(k-K%| zLc_B z^;5!yubH>BPZT9`{MRh>Cgu+~#Z0E6G<2gM(=OJ93ah?`^W=VpZgNQoBn&%+t-T{& zn19%i4tX@3jDY7dX40fr;>$jT&C!li1gyNgS0MxtVhxX;%Xf@)~FaS-@F>f8YE{1JIBI+|rlSXmOp@8PZ z@Fl~_WszLTi(_1{ECN{H_2O<@>oIcyGMP+H;RsQra`@HAc~RQ642X3h4Od(B!oCi* z2BC_5GN5rOqFi{9$$!*eiCN-Ddi34WZR|24t~m#LJ_Z3eUM}>ZJ@bocG{sAPWTcmX zUx6WKEGNh`YlQZ!3bM@g<33;YNslBn1at?*YklpFb86S$a;KSPb6V=^tIL%A^^Ufg zRqbA>`!*GBs(jP~;9fBeHV!T2Dk53j@&0{OL6UhtCi6YtQR^H8k0`q(Jf%}8EtCE1 zgs6fEUdGF*dJFy{YLgmAcm_Okn|+6Sb?Blums_T}$cOvK2lKE<<}ZT|mNl)A1I~ey z8!{)=_kAl--zLSUQJl8IgwF}He*^ek5FvhW@T}A1;WD#>nmV9a%4`?0H*Rh;wn(nm zBl@9KiCUx&7);RAHKu-FCpOr%PqDuQaBV7Gx8|_2SbxYTtgO(CGz+cYgg@^~~>a zSnvsOHaa@xRbd?hr29sjwM)H3PZ3Gt?d%d8*k3d^JsgBpCPi_LuWwQYj|tYu+J5U1 ze3CT`V>r;00QK0me!?NPBk0~`>c~txt&dU&02=BenSLY_**QmQt!xRdy0@dI@CJ#% zr+6@$Xn|YkLedw*xMub*zrFc~EGkO_z%vgyz@vt}JPQO9y;bUrIaCiUCUwS^u5G%u zF#vy>U<1ei=&6KnF4IfG*iiuS$(xS zPtlT%JYzHiK7)5sl}_R4(hgB;eiMuyU!dfC$jP!ko)PG!46*s5Lfl}EQMHLK6YxR? z*@t7;WsMB_40++xIO29hP$1s28V}UwFHINQ`fcw?8DuG{{y`MI;f%SEq9)bR4s1VY zt;Q#<`{K`;d-b3Q;8JiNEza01I#kc&HYAJmrzKU$1=i5CQ_CR2UVMPOZmvR=|(Nx zQgBq)xe!yv&I)gVRoYeU2#?>!p!H!7Ow)?d;%6u&TiOq}ytuQAwsHOpMCW)~Bv9tO zHrW|^eQ<~q2>g_C&i^E+c!kGeZlS#yaS~Lgs$gn6D?AFKl7=Y=I&-QXx!UgmMqkwg zs|s>Hn79jXb-YHj7rG|A1q%rZX|@knE8;|=uy6J|!eY?7ClV3AVjS9)#Nj}i1vDlX zUMT`%$?W&OBwdv#T9mrBaQ;4gx)8zjhafDM+&X&VRobrRKm#J(mUo*HmaOnQPVGq$ zZQe29dv)9rv3b73;wjb`78)+^<=tRB`qNFZ!lPh zJU~yI!QAXoW3%a|ycWSoZbY8!CXx=x_^=LYaBR`TZV{q_?CT>iEB)o2g*(UjD@Ge` zwdv9^QHb;i$VuA|tt<)-1#)fua!dcoOgizG?f_jd=KcJ0fW=6`I1T-|khEKt10{|h9cwixVWbLMBUaw<{Ag7-LSQ>gOe1$ z{@hHSB1uFN?Ivk0iue|UUnq}C7pcTpw-U{QgRbs5=lUr<5msg8;_FaVWXMy3ufPanKp*>JxtqNZ z4cZ|z$tpP&bVmrpr}DG^+Gq1 zr%`92sr78s@^a(#*%%U_mgxqfT5RRfd`nH@jQP_<&#Zz7R-?+7EB>g3ArWzgVbsTc zO&_|vrLQ^1cVzMMMB949@&XekaF*zV;H2EmHwyEmzgib~Dq}H9aivHsWC!~LL?c;(+rwV)>TC#4{q&p^FW`Sz zQzb-dnLyRjiZa6W&{Ji3pXY3XWh%rt1hwSXdG}ANQL2mUcUTDVEX>={=F7(dRy zYDR{+$-6?_^JF>x>yL6oN4l54HD5#@yiv}1(rm4yk*a_SIsGrfZT6II~SkplmlKJHs4 z{hIxjBD11@zxKRcWnhLw8!&>X3nKE zVHFBMbl77jLbRJAGL~NE{73FY%)jYc_mL0^1oME5s2BTS^JBG5-)4I?n!(Wm)b{7q z?@02?K(yE#h_`Ka5rcMedG~>;OFe<59~2xtRP{`4Eq-yT zx3|7QY#X%IHwp+J)w5-u_>mc^O|~Wn(rG5o-7>Hf;)(1Fp6yB_qIjYSmO>^a`fpv% z@Tv>2zaR7cqCmeIhdma@@4S`SP<`HYN7Fc@_$7b0Vq&gmc?4C6RQPJwzPdEIeeJNjXLDt=ev83^H zOO0u-S!fDppFrg&gQV@}AroXU)e~oxE*7@r$Xnl0bNYpZ0l7*%IpHva=w2|T4J7MF zei0L_FMyba{=Nq(Vu|)sEAbrlQ>4wg(aU3@YY7Nw&Gf?;G>(nNsAixmZr{91<4Don zLD4!r-qckU{X+V|eWbl1f$kknI`S3nCxoA9GvO)L*P{f6FQ-cjcuB_zmWZMjgH6uc3r+F7h7M}q|2mk_4b zY9)B^Un{At!GD={DIz>`$Zc_BL%fbOo2RrD?c&g-)Art_wIdASJ+$Tm4CBdVN;q{B zQa#CRL<*rx5{|b!xJ+5R;yw)7fE=pJuHXijG)ZaF8k_r8AXh-Eb8;R|CiSJ341LLe zA*}oDO|A;3H%_?=T_J)oJIvGR&`C)1GU&m9-{*q^4qq)U&>zPGz%r>cJk|zYz&=CP z<#xNxHCpmNd~;kcG&hT;k#7bRDP6vdR*a`^XW6JTD(}!t0yH`m-NVi`4SaH-YxK^o zI+<XDl@qH<92FXWw4IRac}{dL%5IH$|qBszts z`Ctd%tI;c@am`~pgUkS<(bp#Cd!da8|C@eMe;PPOKk{jd+Dvhawi?7OzmJu6^{!E? zY%~e2_zpzaEq0kQS)YCrxh70rOgmQf1bRONi|sP8!C_sgWoih1Y)Ep>i_h7Ic{k-X zJqXkXp-J*@I)F11Sf**E8rp$RES}PZrzPZdwPzs2Kfwk0>S*qgp>l}Hzp12}nw&dK z7ve0zCYzdNTK-f8?@$OFUl6ufc)k;s-7d?xebVzrv(*;6Zyu`z%)wu?W;1R24~{rq zhpEP38)R@lBP%l%-zzHdj#_K0a$}VS!JF*t#a?SFFBJK_1apBr+vD!hTpNxK~0ukag4o*o>P<4#d6=xjv&J#B+>J&y4O)jS_VIBx8>T5F!H8$Q{NA zp=%0du|x~h?nV~f#?Q@^wM>Wui#4XRMn%0Hyi44n=&g}O1jnhkvh|86;D|7Y(|9Q= ztUz<75^ehw_&<@h^5T?7=SzRyB>!4>Mk%r`%1r-Weovn`#DMZ?bHT8wGx+Pw-!y$z;b)By0M-MSq#p4LMlQ(T9Cje2zGM*+l{CScF9M`sm^}P z(v!mcXTDd!EFU=*ra0DBp>eDG0PUbmQje7bZpx{SxxRAbLU#yy+^bp;tgB!u7Wlwn zmqIz`jFeXx{MOv8jXGIim_!PYpK7qPoF+XBgG@cls$HAj!7nZC+l=kd$9+;lY_7dP z(85ayomh8Rzs|}IP2e#OgZC5uXmm(-r-4|w{!p^54iYboT2WYMYLpzmnOaSQij~j>XL)ZKlZmhA+HXooF(_ot5McNT_`3*r~E0qv+ zJlpHO3$XimBefk8adIi{aS*x`sW>V6wThLnJftII8>@$(UI(?MJq@c1A?*qN>#Ikp z2WhRKl1-e_AHK|+{+KH@c619i>ggX#3~&3MYHaxLK#ofrv2l3MU8lNrVLufJ<>e)b zW#_wdkl7^G3SDdVYAMchDmw#i$y|3E#B3J}Gm=$(5Hj?# z_Xu`zp-!kriOLMzgjasPsrA)dc(lsW%==h(a*lLbxA+46?$l)0-{|&!)F2Bk9I|@W zXi?)jH~17N(&#_U)P7D_G%j&YBCmPCM^RB8IjdHecOdW{aTi}2BS)aaP)1EEwj(Y1 zD^a!DI{>h!f0^@Uwk9he>L4n8%^IhHn}?VWU}~cmfEC^bMvc9$@gNK^1mO1V$F*Cm zHGsH^Vy*0z${Rapcmd4FZK)(shOHf zx+w(z`wZ_LvcI?&?dq^?E3Euk3`KqLH@q-&th)Ku(&nA7tRzR=FJ2N=h9w0rbnt&L2shqA-;~Q5FTKw$9=!w4Dv$N;R?3J^_8RI;ES$`)ilC5@36TY1VEt70_pEk2aq#~4!VbX z4m>oFL~zq1H^@cGfE?A=z0Mu*O^BoH6$R_HtTT9RIJzJ?#SY}!L&y-$w+kUr9%~#b z;N45O1GNR8b1{kSxPq*q%5E0j?>RShm@hebzG(^_S?r^G<#l17(uArTBeQna zzXC8b0JK%W_PCgB=tajVywN&DdEe;CM|oo>NSAJfsi)CSj`O4G`^|GPhk)l%k$k-F*^wb>2pf?;y)3k8HR)<;Ft{ik}LawL8l{`y8JrsS^m9Yk6k|6@a| zf0;D3qo>Ho_xRLM^4ycSn}aCXZwn^mlM48r;K?)0!fCJ~e*y)juS^4&&my8t8`JKh zWyb#CxDB_Bk1C(74&j{La}v@M#t}abMKS|%jK_*4--@@ko#42D_xzgWOe6?lS3)Bb z)Q-hn+~;!uEl>X!n7rj@}9qm~8@KL_&@{0srlN9)y!n@9iAWg4XewTy8#IdUo>kKA2; zG1AgiYQLK$`~GmRe<@7c?ZutzCLXHZ&bZOfMc+4$D4BC4!BaAHXW7UWwy;SSb3^`V zxY`wQ?Cqr9ekBN?pSoTU1}E33ej5vM3g{lkx!$^Xq*3dm06~`g#}>{O zZd#JcfyxzxKL>4qP|8BP_`=yybLpTi7oy%&nfx921#yqwM4P)BqCWe~5neALhdy5k zB9cFUx_^^2+SRaWo1Uj&pYb!(4B*gan1!~Jv1ZeY0MQA_64X%o>Htx8{GkxzR_E-bJ1OqSQCOgbzcFc+(BB)0z%D%0!lcFva-k4?c}4B~$a? ztL(nw4N1Z`i3&il8WeiqWS*1qxNpB+$-g4H#t*&~^ArI9p>d>PXIADOA)h-5@6SP2 z%~+AI7K0B{WDC4;TKKOqRT-_0*mf4OB@&aqFXn+HAa*fatwv;qE^54`hpxbw)?wie zMv-9?EEXMc1Qu=q`5Kn7TreyfV6ucUQ1mFC9p-Pox)v@12~m^v5B%V1m`QteZ$L{f z$y^43-2EGM3%j=4gD?z$1AY4;*|C|g8jJ>l5VDJ3BvWca=Nd-- zT5Sz^RD31zc2ghKR8l^SEtwt~u3Je01UXd02^;QPRT>136ePSiC{-9I&jnX=v#Ab&=#za87dT1!VWmu#aLJcOiO* zY+Gp@9Rx5x02mFgea@Dk@jdfwfzdMpSS2j}LEJDiXR$c$>^_EN#4=M!{@wIhJSuwN ze|f*(=e9krR}y$;BBj!cX=E-1(z2jgU*jkkik`M8JEVZu{bEjnoG#p42zC6 zjM$Bu^del02usn>@_k}&zhV_R7?>+YGvKBqbc6_tK|Gu`|3wHlpr57XfQzw!Z0$Ij zrK*Vw&QV0XVxE#J$3a%gEOi7gVr{%v@c+6?_X?(+X z+rZ{N?^sa^C&xMv&YkBk)TWB&W3dS0gG;N1cq~q+Ug{(?KfU}w-N%=FtZqdo%0ck? z8)@>#Q}3`W!vjK|AlDo1c%nU&iZiJ5je6PbppAr5tchr`;Z_2c zNtXFj&q6e_vm2u}LKMF5bX?gH@fHI}-c0<(JAo|^w0JLaIg6^{@3+=Iu7EkX&n7Nlou{Vpbp_3d4xS~KpE&$hPqJ`{I{t= zx)0hdbb2Z5>;j83IVUn#O(_?&coaHb;Q>70HoUnPJ*9Pl8xILsiT8GJNF^y+6=|`m z0Khd-_;ykA$-GZYnnDIXWZ2~RL++_TFb4kv?poTFiP3rYGqL~Q$X5)n02es9!Zj%wm9!P&yXs8y}ch8SHBV2nmEenYi4{o)PwQwWQi}@h&sSo zrfXK{%W&Ih6=YNL&ZuE@2`RZ6zk4OZSLZ+zN^KSJdfuDQR8pI?4s^&#NFZ-?987IU zrc$8_qd&>IzzlTP(&M<#3J9+{30KtSz2U$dG0T_W^FMEeuJ#>b$ST;ymTwvhbW==k z5`k$Ocm;U+7`>Wjh9libI(Qc!yF|FSPWtP+m|ILJ<4pn=e~DUt?ie%dXAWec%PfPx z?3>epRL3u}H!eN@V0QLm{SiW90F~In3tj*9M&|l-+Uu66!v zJ?_q}BbWZmou7Y)V-RX+^h8%3El<*?qQOBbF}6LRJ&Bo^Kw=!hrPMv|7|#lT@}(Zg z-dol)8rv{eN=84sFsK3rjT2NVj5f&-u%ipjr7$fR1aG5E^TU)h+m@$z$mkRi+ieHX z>eX$v5NLW>oo?10Frrj* z5TU7PX;V)im}H5}Vd&9Vfj(B>7NzY#=Ts**c+O@}PGnSv! zg4}(X4?KdtZ_D5z)(`V6iHH(^PC?Q_&~u7*N`E9Tj3|kL2c&oK3re0A$+^61Uii8+ z=KUQqee!mz8!6yZJdRB^CAE&#W}4?GI$rH&6$(6P=9CMJV<9}%PJmyS-SAWiQus%`H?Y@0LOjJV@(CdK%>bWfqB z^%XMbyF}=wd3{}P9$FgQT=`l72SDb<^-#6uN!f2=_;tqk0e?8HEYm zfmUU>U~5QX<6f-oPNQ$oY3myAs{_v`s{SdpPkK9q)h#C(S9uDIoF*05X#YtATlFi< zx#Q6EcjLij>Ch4Mq*Ft~{pzStDObeA?u9$adZy}P8Ux~n!{w;TCLdM{2^yl6KJJaD zvBV}N5?r0lFI(3Wt&cFsen?APnS5S-wBb4O!72Tr^%+gU^Tbz2egqjK>=&+-8-RBq z8x_L|Tpz1~oD|0hI6j_seU912 z)2vzl6lNG06m=U-qpUkgWkGqnNxF ziy;eU6{qr7vB%yfS6|ue$h`%UFt5bTyGYO0F>KF}Ie$qicCOEk`24mfPVNvrzgnGu zdM+Ycd!|r8cf7P5m|8thBt1Lj$O7^kQU}&Ig{I_DT&C4!(v7h`&Llej39kwMbu~UG zV`Ou_>wkUS?+nM2B4`iXwf>UEv$EZ$*=`$59N!mpoFe$1(`*qaKKRM` zflZ5TO%dhVCuOND&4(S~LD%`y0?g=d{3*O$lK=(6aemeSgh}1^5bQS`xNU-FtRISW zQ)eQR(`=0U`kL_L-72g9Yi1u90QjGP%KuP617je}V)>t@_6c%1_yJjGK?mbHK*qa1R3v7!?AUgLKT)tz`p01y4_Iit}NU-efB4_Qzye*H@=WU#_aSpY~A_ z`2x``ApimZ*u5eQG|pG+YV;C?^ZKQS;=dqU5`FgKBcmugW@xH`s_g`VM0bTuuwd@N z28U|x^`AuwQ4688Q93{@VLt=iM zu`L9ie>kXqaCC|erH|vgWKzETRxBnul{{VtNQKlb3mW(GE_VXsa^`!0T3bcxBrBeB z2=W%>moc*2fOm(Hd7UB-kOq*^_4VT{EH{=av>r1phja!6r>TC%ngH$z?qo?`-&N%| zM6a;YtCA^X>8fk%PeM#!Rs)qZ5JmoNF(O&*8?@Q+ELL&Tncn^Ue8YHN%5rY78**0K zZJjx`0Y_7si7KMD0f7`~+huhM$>&DppaU_Y3`d?v1k&d{T$kdGJOQ3S$@B~^i;a6OWwI>#W4YhO><%<%hJ2{ zST%q8wb+4?t_pK7v#~D;WlE}{(7~Zhp{wxBtrYy?2Y!)MfEch`RuEZ)h7YL|y#_;~ zvdFB0X|)`32GE*bz2t6`*6i;p9JK%thmRA>td(s>Q;mO0=z&`T+mlQr0w5Md(b((^U)*Ss`m>1-t!)pV8dVm*^si3c&{&az<% z+>_SkFP(0BabX&k#dIapR<8|tF<20t zmw?MKgu+|T$po(py_{}HJ;vWgEt_Ho4Jc~V{E=pGo5?R`EQy*wc*YCRg+nB-&0YSi zDZIx@EiAAS+y9viKJa98(6P-Ld*fI8pdZ6jy0&Tg)yO=O$?4B-j1R(2fEc~vAN4h2 zIVec#jyD4q6y=l&@1JU;9Sly3vaGZ92`U)Qth=kz<$-yT16F|nItb0}oL{Dz#TKB) zLQNDFY=wCc=G~AR?x?zRN{2bPw}Hi*oRnTIi=CGC1Oy8GkelTR%5HB?k;&wWR+hC1 zzfrom$+>6u1e}&;BxI)c$)!N(cdCO}UFSR=E9(I&MN95`9XoO2ow|Sr4SWA;6V~ff z>(=>@xY&NEWo5}H%AP+`8^)B91b*?rJ=C%$Yl4J=W>;^W+!Feu8d+rry4F6EZ4|QI zMe@9Dt2w=wZ+xvt#vdo=d4a^!WKtUvJ78~_5{+kI&7u=na5acs^0%9;^isn70#XwE z@mTcj86V`_e^zxR=#T>pUSeBxddplarEKDG@5u78dKJ_aAIc`ah02Sv2i^BvMsG+R?5jc3}S4mfu-rlhW z(3`g#^$^m0xyc;DMd9dR2*aFrYE1yBi{7wIFSyBeSc=1)fzE{W5&JWJ_}O5gyW4+f zu0Qo|IesyX8@AQCgk{b&;Ug}y=ci``5eD0H8}Hn121Qjw<3UBr7~UPGY072*B@ad2 z18PE6;tNg=*#G+Dm|=fC;%sKaq>4eHgNItR@nh$7{SwI@;m^_e?DY4v@(CRDhxHb@ zYpW$qR(J@}cCp2^hw&vzOc>Bq?72F);NNd~s9&uc$^QPRW4myg9E3l*?*~jJFA%Oi zavDpj6^(CD^;mX5Nqu7r%;#&+4D2oSt4(pz1VTTUm9qU)M-Ary0N84A@>!&>*8;3< z2r0Rr@)ddZ8=8N2fki4J%inc`e5k?-G0r4Q4- z9$e(u6)=RBRaLpPM$nDbbDE=uj(c!yMqwWKWPC7gzD&U&D1Bm1>jCN{9q`x;bhq!) z%;11B>@XHo6nG&@)eIM96?JPI4qIoN-rkbnRNnNrS`4MePtR&qpvV3aKIT z*~Qv-YhL9g;zg^l`)6*kFdNeCH2yi*;OJ3e(@%7bUx73bjSE%8QOB7-%Sku<)_Jx` zwUhS@1j>$2Ia1$zP^0&3s#t@rV7x71?9V(dgNwZ)6JN3dHiInUCiN5AQ|o#5WInm9 z_$tnfPpFKiBw-*5_3@o4PPmB;Yvf%MtfRAV%@WXI$p(h-Wm5E|x%2;`3f-`Ahy14Tsjv>+!A=dh=fmj&CHpw@;4UfuBtBz>9GJ%-*?R3pZDY zfMj=TUDY*+lE#~pQQVBGp9enGjm48%%l>$c`$5qQdCe}H7)YVZp&?+gs2)#Qh$6$v zdUXtWL9rrgln40;1k6)`M}m?ncUJt}!Q1)3-3+#Dj8f$y*+7K(n$yg({f34ztoRbI zOTwQygZwew9FG%{(BT-4*PwE0OXk7-V4R%_OAWv9O&VEUR5ib`N2S>fXB<`T4F!OL_eK^hd`)gf5|Z334w77`A>NFQ0(EEc6uO_TvSCg z8xk#Gl}Z?hY#XuG7;f+rJ8(Hm;U)D>9@DL4g3T^9gLPaBK2EbaM86z9Rpo4H&k{5Eax&pFlrO8R^A zlON|zNYD1#&?pexT^)WH88Ob}n9d4a|uq&7*O zsThSw3<;xz%-+&qb&Zg#K*_rccw%a|Y-FIC)V0bC0)=z@nmMQ0)$lhq zov5p}hessJ59Dbdh>f;FzeuI>R*F_J08c&;!O}>S7?Nrb*#nSoUZabyO7=OV;J;iZ zFfiJG`AiT`!Yq#e$!7ush8yh@0oFOZ83QhcNU3OA7;4sJ_;%xnoaLt;->Owaqb@UKG_ z0X}3~vV3&$%uDsQ!cmmW%Leu9FNs{Sr0#Hk?&)xez5U zgpBppjG6PhXjFv&d2dvi^mPB`%^t66(p%gqk_!i50;8loD_WE4G4$>e9}k)Fer*a3 zXs6VVxC^m^8G4T!#?}JI-t5E&TtRc`A>ZPuW?%Lq8oe9TV?6FOw8VlVuerFV(TFf9 zWs9`tmH?0ovcLamc9H7)j>UkC>HCY{5vo z6VE?`hYjca>_VIpfMR`hv4ofOC-SsaVTJP6ZtB*@&_&su5e9JKrmfsBLleGRrII=0!NOOc$s7AGx;)jbRd2beUP|aYRyaQvC${r1kthn(y>Cmrq;FnTOvS z6W^kD&dv4r)~VPPrNYS#i&1U+Hg7@%;qpFil0zRCFjF+9)PUl_)bZ=71V^ALwCQS2 zmk&(8j>oj3M6*CaL{_8x!Y?xN8a@6T%Wc}mAtHjEjbRfVA{G3VKc!3h%Xsr+ne zMv!bllQzMIP7_Tz2Qc^2X4p1*>5)~1hBr+3VG}ja3^bsleMJ6$1IY7D&Cdt(B4?-E zvp9FgI_ImCJ$TronYB)zCm6Arw(YEHnP%H3(puY0x5N-SHKwgh%hq2krv7XO1xtJ! z0r=fNtgyem&1Q&v{B)|7Iir!Fiswla#0DdG4_EB9*}lt4@cp?pdke2*Kp$LRUqT^$wWn-lxd@sc=&=z=#_HhNI={q45IOeBZ%sqCpR ztz1ESulVL?m!sA}{6f8rE2RZwK&L`YZ$NR>y;aV`zgM9uZpPe!$JPbPOK(OZ&qlfi zK`J_Z>REHLc!rDgo!J`}Tdnl0VKR5WD{;T@wg7h$znUZ>yG{NEFmUc9cdage{i@@r zxUnn`VCrc|(|+kN1OlJ`nbYsDDNi@)3Z-k*C#a<{bz z0O`w>^V)&nU8rZD&@xojo>!)MK~(_MgRXoZ!w(iiLoC)Pe`m4yx6J>4Z0Q3Aq9cb9 zCIA5f1PBlyK!Et)Gnmnj|2eRK559c)(#6wiOf_ zumAsqG4LPY{(DgV2e|*{KlmTu{sY|q$}|4Q$Ne{>$A5tP4{-mlNz8xJk^g39_aET? z1Kj@?srV0b_}^n%|2IGT4{-kh?th=X{)ajIhdKQJ%pCqzg@7RcsX>5B5@vDzKPuaa zM55`bp}u!QP_|D#r2&oEBP!we+k6H2F&S#HU1V6J+UuQNVgDC?(TjA z!6gI@t_kiIECkm;aEAa11PcVe!3nNGf)gybI|PRi+$H$W?o0?X*_m&4v%BB_opaCO zaJs9jtDbu5?Rx7zZ&mmGhfTW@9dMlU#5w_CeP4EIr2_fiWp?n1haa(Ko}_Ng3gPcH zvmuY`WtjruVD5H5qI$@|izMuWUv}Zp9$W@xH{W`CezpRf_%f6413U99#yOhtGcl~} z!&O_Gw_Q)jn`rPpQwN}NE*+`Mf>BHjYLZE80x*h_uoG1E8fQN03*~7&TW9y>ok5ZD zRJ{)jPRx%L5K?%BTqIy6eDoN~FycMys|QjqpOlKJ7BU*A7;6plnoY!JdSz0!LBD@fqKvG&q(xlQ}=} zE!V&S`_0cAC$J&x6S38%C5T;*-5o-E$_1_V0XS+4w~)$IwK?=2-9l3+d5iwSsLMp{ zcAIzCD;9bYMk^acx;TlH7vmw&nMbaL#s}U1;4=#CRS6n@+9n z!uQ-6qg{QJK%4x#(b?*A11L4v%$}o{z|UzCbxES_oFCLadSV`*Tfgr;rBb+ zv=EKIoN(cXrv=m*sACv8a>6jROyt^<$BgWD$t4W%Pu%%r)hJ&h{va@;zb5tD_??Zj#+U7#!`6%Y;#-1Gg58`v!n7JJgKNopyUxg`5>r; zF_0-2k|*}=J!i(q*sW((ImTZqHTBx_Jqk&4shW)t%%$r-=N}!02k_!by`mi#Ta?E& zgEjEmv&_K8?S#=T-asvq7w$7SAXw({b1}rU_P9_$e61y1=nz4*r}mkSqhnPJ6DzBR zQyO)LNE^XerAxFQ=j|6D%Kn2VT!tFVt`uBfUK-m})%XK$=X?=7Iep|Dfc_dON+&M> z6|oZAxFL=jrrSmAp z<3&xL4gDD6v-_E6*_juS`4>=&iHG;?$Kur{@~t+NlZUc6!Y(+EVV1}1#m1?E=pQnf zTgBh<@`Lm7PVt+-NU0nY-hU^s20)v*+Ak{=Z=D6|v6dWRHNhB8Gn7)(G<1K*Pt%Pp z1mg{3+TlXP^bpXI4H*A|4R|M1+af!keQJ<2lFNpvFh_-I&(E1YxS*{}P+bX7DNMz=)oKB!%7RbbVJJvBecy^NV#f>SX!Nsl)KqUGB*8(d1(!S(2JTM#s z>t|-)@q`(7C_n2!`CzpzKex%zck5}J_d9~JtsK109BDMQtmu1#d!`r468NWKpF38W z$nfUZmUi3Nh{b(LEhwlIBS%wWk;(359htCR=}OuNvAe}U?oZ4w6)qM)Nu(CH1V}oE zNkU*hsh0u=B{WswZW}Vky?()G{>DuB$nX*tteMBE7`+Wk902G%L1dj`3~e`mgb(Y3 z9;2BhJkh$b6J?sSBhr%euGd*cSzFR%mjZXwO;F}`grHRCFyawE)GNy{Js}viNDWD? zR6orn9Ib`KQKoUQu%=fz?)uF>?n$@Fv)@-@CEK;w1dCzHNg_h0{ z2aQJdsYE=zs`b6bRo2#hV{tZj4@rC@Z(Kb2-1%)dY1iCTM)l@4c3bXEVZgvnPMRt8 z+Y*^TE|kZejNAO$4Z=L9-tzMmRAfVnP%o!Bq5D^8m_K5*NQYH>0H34uFBB&V!N9(d z#FpF%Rc%J);wa-HCSuRG)wQPUlJF_JNO9EztJz2xg46>v=Zz$&AmJrwNLt-R~(sty~1$ zJMRbqmrmCqbt+Id%G{ejk>%4Ke8J_*4x>(DT1)<@_#QrI(ttAEqIfiQ6QGD<2zGg! zcgV1`x7Vn6{MACKF3l^{sKXHkvOp^aX}DhQ!sYVaYfuB>J5Vr5p7UfVnYRUk zTm%g77)0X2wd`hLi53nXuO6r7&Ryli!H*`W6RI$lsP8v8I2xzST`nZhOfsj-M4l+ zM#CL)m5zO>wdrHazOjho`~JfP*Fae&v+yFbAHnU87b72-cvktgPdbpt9Mn$472;xy}cN?G4ZMBp@FqKE~+4iR%pMbG7{v$iA{YRy@>~*l)tzQU{nqOi0HGBqCzJ?VB0*m|(me&YQ@hVwFY^V^; zUN)cw0kaStTT#t-bJCP*A}w2;0nXkQYQQ8@qXoZ6Vx>fpB6;51h9kt$V{CoFkHu5EWIlxX7)4}mFTy$CV&8E5cvLYs)q)8jcBhEWQVk`he$&@K-idrDs^}@YG$1=rLNN<5J1ri~PpKI6`#XNmz1a56b` zutN2N(Qk+gs{Ou~`#TbTIn5rT+0v%P@x~?D;I^3ko*BmdngV|iSmp;1Mw9iySp95P zl=DJ3pPI`2#-N#bM*KIjgYjoo^ht#y=mUin?y!H(Xjv?Gd zdLoBZ`N{QH9?T!}Kps`dqY8Oc|LDi& zPp1Eyf2&^WTuvac+nkkBJH~dkPHGV{0N{IF0KCI+uBykcgRQB(5NJL z7xGO#Ct@2sVef;62=8XS#f65J)3kh2wTS^h_7E2AFV(l0Of6ftJM%izzo#N*gP$&( z>MW>Cock`z(=l*06kbG8nATFj%((HK;v0&a0`1?AVc57P#l!f)-rsXTkzFGl0D+Z$ z5-EpF>Dns0og8t>c*0WJIssmO@dy-Ur0#x%8S1KPq-BTCDfFtn>(HK|7n`u6j$%G- zwmo&WhTqv|1A3tBeS?331AK%OXw7TxRE4g0d$0q$VkI;2Z|L6cJQz5C=CRyob?a&!FYuEf=tzG-a z+W#rT{R7f}q2ilPf1~j{dNw9ce?(KY1qt>T)fLlcH*#sC9{$ z^not2aFO-Z8%mE)H_YduDt4Sw;Woi3PdHmt9#ZD?lIN~%WEKIr1G#jLnx;^ROXm~| zW~hp!j74`Op2;bxC_cFuh)eb=$&nUY=(<-k9258QtgVgsWrZj#hGPuDs6N7ACZ=Im z$HE($>P%_8&OR~*Blmv4a#hu27A1_&oohBvhqxw8u&>v@|EMto-^`kzDA&d$-%we< zZ{GnNgTSUg((=z3WPVB}rlb;w`0Xd-lwy9pVGXmeDaI)qy2WKr8BU_^DgQn=*wH*_RzYT%4{tl^NunPMH7jAH2o+2vqIToet@P|_sGyti8q+U&6ruuBsBRvHZ7H5+swu;q_z{IgG~ zkfXHOTLALO-M5`UuK6rP2alw~6S9Rmqvjn}{Q>GrlXZp!4qBcDLM^pzQe|_kc#@RQ z0s-SO+Nj4C9sN`uuS7o)tLPH+FUj;AV;-* z%ZGBksRYOm0zdhA%Kla{@ZKRxw=3-XVOL4)^q%_(;B3#(`MddC`!vsQa}06^A#4iT>r2M#&1;0E;`e_GuR=lgEsymL}v5nPI z$vMeOHW?<_!0;JD0(i!%)2cKmd1@xu^YoQM z6hli$4m_D0GvV(|7RX*%qEoBP=#4s{@NpFO(Wh&=v95Mx{1PVxB7nd)KhpTm3`N%i z0Cs#^&Knt~%hN%v0+bd#6)K&NWW8iGLN5Y|fQ1hC94C&~zKqvC>9M>0+U0B}Acr36 z*u@o#o+zmpTo|*|Nk$tB!iv)eB0zIJV^Xd(xAd^o91jgn0Zzuq9Gc~{G z1^Q{3Ze0${)XntGD{g*`9KQsCZU0S-;7TPQhMu=_^sJJwPD5LSzlV{osg@$wOTVh^ z+T{O!fGPLc-e%7R|3*68TZm@-qaOTMQXrZ!L^FnH#((k)^=B?Ye%=26@#_}i9R7+c z_%RQ}IY68P#5w$o2l$hFAzg#1XIaKmv-8fFdNI_}}xY*Gg9r2yFkO z()G`(&VSdhfX3M~B5w~9E|pv&`23y5HgYQ;Nz5!>wPkuDCoWmZiCn zRcrnR%U8bD8L!MXid0y~k{;6%>4xt0OL;V_>XHhB1NAp9C<$F7&j5iP|6Rxp#ZU+1 zhA-FFP2VI$J!*a*fLZBbncgZ?`~0#%ojvk1JG+eQ`9@ta+1;_)L|Qt(5{&b-H#cDY z9WSh3M^R66P0-DB;FX&9tET7+0z3bR_g_+3ffVttLAJ1IvbGdJ1)IEFG{;kx>Y{*~ z6$9|HbDGSLcQtM#BE?>Vxq45P>%R%i-&9QfrvTI`9O<+YUYU_viM=gY5H1`kdS&79 zKs^0Na?-j{rmgQdJV)&uwvwH$cCY-Mw!i%st-nSV0Rp@Ki0of7$ZzEXSKG!GtD-TE z*eu9=)(`~lbMM|Km7eXtB%W|IU1L*eucMat{sj&2@sqr}?6qt+!Ew)CgS*m&J^#(% z0DzN4OWVwu4kI>;NRD8ap++~Xq(iY=3kSbK0&q+zr}sq#KWzB2Y@M;ZXbop&v*k3EY&xHfKVW?&%YfF zG(f`9$T4w-&164L6wL$^-u1vE>FkAH=8T8M0psE>hd3=-O%B$9GP@3zD+6QiqKYY5 z0r$qM$8>4N))qUGaDMj$MQEDvyntS$`6uK%5-uLu&1L=sJ`W=c&Q_VY$4^|6y-BwYmS&E| z*{$wpu5qau2X?8JGk0v0ukL`t;Lv%v*7iO00}X(>ddJOKX^`ONGl{dVX7@(YcHh^}2|Kob=7dGGoH-?2Z zY?W89y1JgJ4?<)`M`J@Y+r2&zfPEhE}wqijTP;)!aG_ywwkR0lYIr7 zZ>FVcTV3`1+oMue(hGb?09Y{??k`HtdOYw_fI@Ko#1t8Z6~0{)1b69$`4z3-u%VBx zWJfW6&OUW=C>r5Z;|W1E(8tuGwfS&)zB~-Q;vsS5b=u@HAbs_oG(>04|M1P=TUPzZ$`M+kV@M!7gfR%YCpYCSt{WV@Lcy2v5W?>*!h$e^M&i*h9F9b~8= zBIEyIsm_W06;FX#9@_3&ibCf8YpzR;@Np_uMy5BEh@^)3nn6JCz;?QU@oK#lf`)5U`V_wh zs!Z;k3Ou|0N#58#MeSZlxJNEEZGGr1Me#!T=CY1=fb6w_kjL;#007Jucl2%Z0UU1> zo=y1h{KrVvF2p&(ioimgZ}g#D1(|+TlXXGh;2-JxH)!6#;Hs;yBh?{MY+iI;u5|ZH zEUbO7T1nqytak9+=4;{n)X6Qsl^<$a?W0}3k;~98eZlu9j)FoG7eJ%msG-{-&+iRDcmxzCch;u6 z!3Q+Z=$a5i5IF2dLVkYe!w3Ya+%*x#=dJy4*5bLW(rnxM$@2ab-_PF{k65 zG+8$Rawt)V&6|;n*P>Dz27Sa>4`a$1&HFl)70qqx!>T!EHM-`|Je9{bDqkIp_#ULw zVDX=9e8Q%H3j&BzN}ZvvSF}D*mSs+@a0UjxD(hkSw8Ndg)7$x(z_>O36${NnsLJ_a zJQ<}4ZvX&O{G)J8#ZuJ`x)H~&*)9ZuU;l^LHXq_Wo+dr*t*6H!GUauSNz{+CM2J8$ zVLbXOEZAECih{zTN?5EGJH7?*5~7Naxa=RESE?I^ua}rO#OLZiAmMe@H23T68&bez zw&*Z8yT1Z*cNZ2<^53iquvBbkEatYqXAD&WXRI0yZJOJ5Cm0wN(mZOTjB4t;QYlQJ zm10a(!c2a|=yIF;e!6UbDqoMj6QajgZ77nS$Ak8a`x)k=ieA|DGaBA+#>OS^9z@et zZa!z5aoqm6d286uD9r~y7P~C7iD+)r_YQ*R)XMa1xO7HK+VRT8?b>y=%jUCWGiPj0 zOS2QcsoeyL*LWXZI`eQK+bBLj;zP2rf3i}%?2bKXlo1DXF9x%hXwaB7MDy<u z9?IJav7SBg%c~H^l6@|c`PK4yQeXUA9Zays4ez_{fm@HpA zZL{#0*~ePZXQtPYFG}$U(^cA}nBI#L<8uG~5x!bWi8A12R;b_d%hzUL;YVPRy3phqfWr{NuZsZOeS9t?K34N?RUC z3=wou@kUn<)Hj-L9srrU!l;MtbJu5>P;ezSNacE79M-b#g>N$vUW75lg<@@oSQAbO z*w)gQ7CrXgu*+DXQasTNeUlpNVLWZLG11m z4&{6=q76poiV8yR*j}=8$EQ3ew{q?bW(m=ESSz*xjw}QGyd%7bP0Kg}wHn46>sMmxLZeP>P0s_bWj^@98qwBV#Cwgl)XnT~@&Xs9w|3ubybnJ!CMYoFl z>IVcp?#b+_T4L*{hClv16_J~jOvRf@ZMp9?6!zwFd5XC3NEkxiD$a%xy8oyqP5= zFKb;cScvJ@3L)sC!^SQ&l>bD&{+UY<=^G+_L!@tr^nERB z|CIxX^bL`|{{`tAG6DW^a{E_OAQNE71Q;>_{+U_spWF+X07E9g|EDLw*Ls{72n_z6 z9v9BnC=mCM0^TSmNSMZg;1bq)0w=%EEg7VkAxsjA%@Q=38)Yl28I|s&^m>I7=-YTh zu)3D~{(ivwd@81EDA^9%2-xgor|x>9%QE&sVKvpOxK}1o$UuVDy z1M?z9CeH3+LfVk(BL!oUj>mwPtSYS_x&cd`cSq0H?hqrm`za|7s-UJM$<>%gqOGg$ zkDe;$L=^CO+#j0>v_LPIWXvOM<%N$6*`e|e= z{OrSwS1V9d%X$DHyLz+j%PGC&8*Mfhx@Hp%1djh5n_eSWDYbz$xA}4Ib3D{(u!19O zrfb9t05ehv3(HQf?;Ab-a;v-S5?nJ8F2Ok)Xtd#?ccbjz@Cj8~ui(MB%pdCYsvSnD z`}NpTtlL%&@$F{_&an=n`{Np(@2uPCqS?au++U)13sC#-Wg^#EUKVQN7?sg`j~J<> zX)t}HM_9(#Y_=KYb5>d&Gp1Dks6ABQJ9F-)4+y*a62`8vG$_j}v+>dBUJ6B9y@AYv z`Hbs9XDwL-F-0wTak_>ATk9S;|8ZUTlJonf0*4^)DzskeD|uHlBeUmArt3}Y-(Q6Z z6a|43f6q%}R6pLQP}uhBu1C&@6Xgg9QJf+#SZSdGbpq|0-mVWlspzNQJ~*U_YLnZo z{{u>3&HQj=kWdyRsxP*5UtCb2%~t8(GvW5RB%`7tA|5xd%~61tx+tJp%#1B~58}g& zUHL*_*;=fe`;i8F8V4BER8!5;|2~Zu8vO9h=g|00_{y{-s>ZD&CHC~N`@acX1q7*Y%tkV?K$@=X&X?TiqyMww5yRC1{P8 zgh8=SsQt+aUM0sqd~YlXo$hv_pm|WkDo1m^SMuhkxv(jw0o6ME<-e2=i9XS&+TR7UPVDm9O@19+Pwl)=f*+2gWcTc-2UYmRcbxK;M`uKZ;MR=CDjLFYE%Q}B6i_Z>m;h=pOd z;&*B7ICNgZ{qAFwC{B;XF31^ItI;UDqV_?RINU>{B!%!?d{OcWk6sVS-~TLL?Ho?( zl!R1vnNwS;&*3+sF8;w5Zx?@89J~>9Bz;-N?Udtc96wD;$0c%maR)3R!@Plb5^&a=Rc*`2ZjXUJ+_^BT_npi)y zED(MTxK!n*Q#Qoo=c{d7rzp%tol;d!^*ECv&ZkQnI75Tr0;Y>i_xBm&g z0eBo<+j-JZXcPNzEb|8*Fd6 z^xlkR=R-dxWDDr*8;0WFzjCleTf|2>-SU&{ zah&P$H-rjp3N!~KE!Uoq3jv5ukeR9k5g2-__tGb!(v$_n*Y2_NIWl1|=KDMHNu88e zl3ScuI%kI%-i4JVAY$z$?x3X*8p3d9WX|`HEE5fkvJ2gbIp*Tjz9Jd;w%918fN(1vzO zwHd*9mWVTZ-pkHhd2&>#*NhprlRXNE(WIn$^t640@U`8VoQ50xC)?*S`F`Faj~drr zQ6NZKzqx3VbW%~yL#IaF+h^4oI>}Mln_Q7RQ-sFilm#MKxZvZfnJPEsbmQy!O0VeNTlYuxOaL#|G$z6PTBBt}~wb0kYqn+ zFw)h3BdFH<8#{nd5IFA#c2HgUA2b@NA%;!Cun5ts6ub}Kr8X!oe%+4VLM2diLK8)v`EHR0Fc<& zPqQ4i=&!JRyA65?qKo|%73{}65M2zSi$Qd;Khd^+<`P5~gXm)ar*$!iSN+jr{*@Gn zSA}?0h*$j?*ZC*+LcA)(t3tdgWVzK}S!H#d2eRA>vfS!lSZ;MKce#MT1;3HIC=$5n zdAn=q#jEsDaI5YVqYYpooxg+}uJf$GB1MKfnSVgec2d!^?3a7p%;6?Oq^o@o#FU zNT3!?bQsPt&9w~W=C7&|fOo`j;~IB35fvaK;Y8f0D%T7j#X-HghseG z@a$SRktv-7kti_-hnb5q;E^&CB8J0LAM4MD6~7XEaUT{jBKT$;@wX_@V`6u)Yh3Hv zvFr`oaXR#q65)1z_jK5&z7&)PtZWvykr#^PckB?r<1p{IPBDbKY@%ru6uVw}*YatV zjBBzj)!4uMpf9`_bO}dK(fw(!|5Prw^*PN*)382t7;8`T(402$*`Y|oM}1whQ<2>c zF#zKB<0F;FcoR2>fxqhhUz_Ry0>A%VQ-9eVl*P1W*{@+=+@vM;c@Q@QpqxG5J6zr* z#bfXmCVr5v8-__B63p)`bfehcwiIeDSpF+xKVeOMe-bwUDzq<}Zgks$^Cd3gneoz>vyONq=OJa* z>W)8FdI8iEe28r}^_;!+09H8e2ydiXiW@-quTFl&arF#V{Rs|s)j~3We^w;f3QjWz zXX5*36&Q)!y0q=oO`#gQEh(V4BTtn6_z{3VLO9_T0sx=g`#7su!FvM%G_d3vf*S~2 z^8Yo6@2KiVL80r-dQ$Q`4R1w_x(hAS=#$j$xx(LrGYn2BU`EU|*2<%o+h%a5A0o_5lBp&a+9 z@rA74Tjtj{IVUc(w1S4+Q7=dTitWZ~C?be2mj;)~1a-3XCG7~cfjjhKyXDIp%2gxT8A!LY3-&!>b(vgpg90QFGKE5O~TWCZCVJh(i@1t8z|Uq5_p z@iOS!j;ewRGiqJpkMkO8^BQVZvI^TJl0JM7-ssNYn2K)x(8TikwNeb$eIGbJAt$+6 zZ~8Ps56vcnYR{4d@l_-b#NYywan^e6=L);Xi7h?LE4(%*REbcqyiZ+6iLq;|Im)rl zU^cukG@>rtSLtutcIz7(xEO3SA8@r2!%p}->&I^zm<=&F?SiH`**94Sw>V9wI8g+E zNBTl~Xaed&rxy6vqyV)FFwzIBa^)70qFd@B(sy`o=V17B-msNxqk#qhtM}d`ZKC1Z z6k&f-YqQC(++bPRbAdJ`hU!e~3uU%KF%z9P2nC3qblWgQ^i*WA#MZ|rT8r+~#eWqs zjX^cDKx);2UEW0h7!aTy0A){PQwLhp_-GR25PC;9B@nd$g_R_{1b85nrbfK^hH$mZ zLvRjRg#WR!D|&Tk;4<{bu=S4hiY!t3^@LUNptXsjI{F&0c-}ET6JOy`Q?sc3&|Ajb zrw!}j(X-5~uba$s{4<|uy(^aVbJOuv8b8lYok!FE8Y=Zh5``{4bRXptVyM!TH#z;J zj4MhQe4OZr_B~>|SC3hEGzke9y0JXM80se-yDJXw`UIBWdRz!S$F(+qStOrkySN08 z{pnK9T!MI@_0Hm>dp;~qR>OoqI#OXGRjeLvPwL|Sk?N$G0>JEh>&;t*7erE6Atkfh z&+{g+;62~nn-pIfLVa<0-rWU&C*XUuAL_St^Vy`Fg$QMTMHc%p4@4+~2xSnV>`%n5 zpSc7P${<1+L@0v@W!ECuUpasXWe}n4Ul7V56W|{ww|^xCG69B6fFTp$pPA+U$-R&X zFk}M!e|iG^P4Wfofxz{@mwYE4^A1DVuZC@sdJ^B3R9jq0wT+J>C}HoRje14Q-7`v8R2Oqt$f1XuJ(=9DXziQmB)9PjD&FrDxb3Hn`L<^z zw~H-QQkyW+_~gqQai4!ILqdDK%}Gt`xSXqwIn}ei5LGVPefC}%>r)c2{8e z%%g33O}2-tDE-xYrEdwd3J=hQzgnYhGbr8y!1+>0p=wGtKnFAPbPvkp^!0FY^9w&o zwZ3x$^9|h+V&My57mcMCP~i+ zG#+3#47sL1s)}!<&p>c~?+f3eGF#caqHG}*wfdSs9=RTXF5tBSuloKy_l-tj*j#r6 z4G7%)yN>uJ5QMWO+Ev>+<)6#QQ7Wgys?i6_lgN0k<<6d#!6PKueK)>OWN<~MAd7|( z;A>LgmQ@fzaHEDBv>}wVGPfnc&Fy$wpLDrlEI>H z@2QjBTJ7ngK@_C9xI|J>-;gbBIT0t+0mxK~S5uRe<7?Gpk{N+dphJlM`l|sh%X2gNetNh=CB2Yhq?b6mE4DR}iLQM?FHz9} zg8!H9d}-VI8^vCi|F;9E)mS7E;Gw`42Qr@oY^8vJj_t!!RgA4^lfq$6r&wh5&$Axd z66(OTMyn(Q&@HJ-HgsveOjVaV@WrnRtdxZNMvt43rXoW*ZP+S!&PXkK+|u2oF*e;| zOigmhEZ#9bo%Sky7UuT#=xI7hsB~7=UW2|^uHHy`bzoU_6@Epn6N6HaAq_EbvN+6& z9p@c>16PwciKX+G5{H&`yKJG6dwGSfA%y+-qJv`jtDN{j@8)Sup@Ve!A5HrP`v7uk-kI;9sX%v{QC^Tzgg7)!&9{6C&)&1tt}tBRil#GB4(}p$p3@+* zlHfnW2QQK#cr0U?@P8l>UZkx6@Wi`Uv6rRVDFPhaSw%nbWGZ>G24W9TTkh@K=*HRE zir~aAs`I(N2t}HTmSjvw3~u3b&p}XyOM=22nSy`b+J`*|UbH@|sxY~O5n|}U& zs$%aV9_KZCY}<6@PL5njeKMH?g#@ui<>qc1@(R+u&+x4F{_xP%Os!o#UIB;2fz8mq z=xD;se+#gf(Fc#<8AdZw~e!Muu3S^05Qh=!qZS5#(Hv!;0Xq9pNju3ks#} z7>XJM?)rgl>sCTGb8Fw1jisuYBFTkS)C*qCy!X+T$|KGHGwP0Ublb=#9AZV6?6 z09`{en;q*VpO*j}CgRkfP()@{d0=x9CFiJhHqPjHs)ZHgBgu1T1&xIxi;j{Oyx9?G zd3-4MF;m;FpXHYR7oDgu!|`D!kb_CPym&n`x(z_i-%ZJ_ephy*Ux8QaYJOQh z09*rsdwypx4ju0bqbNP2;?iynd<@{wsHZL}&SeI$f-H8jlRV9RJ}b-jt{=d>=wnj) zLt_!Fkd%<4oVfGM|Mr>Hz5Ag)k9L<38b426o)0h9H)k7Ny>{WP(Cl=;t67^5_$Tli z{?R=}vuyoY{dXd;nK@?*buMg$8LN;ZY1%LRQep;Lgm8u6<9S{+J4Lh~%sIS|si=AZ zbBepMdudBi;2SLdaJXMlmHpu;SF4!%YnrK?qeIQ2x3do>0L{&x3dtSMoOVn#tt={~ z6f(nj3YfxEWRmc;1^nqW^R_imVQ_M>Ljq3hv6Oq3r=5#}xWi(f1oT-fxyUl~tH{i3`_A*4hg{8B_)tHg#;|6QV$wAiE%X8Hb zrOtVn_Xou7xd#tk-jgA8!tZ{7>{6UWL5bUC2uAJQtlP`u6M&1=YaOaZ?@li(MBL0H zatvXXsk%J%txe>yfU5bFrv|Wm<(j<@$SV|0y_o099=*fatwJGZ1C=usHNs5n&iwGw zm*d?!>=I1@jQG1OiWOgehgY{IdR}MN$58;#dsK~m5UI$#zdy{ts~7A4(&4U=!oikK-Va}i;4?~Gc9*bltz9m6^!ksn5o^SMG* z(wg-Vf>C zCzO*kWdKhQPNoI{H~m(roWdJLp-GMRYgA^wWgQFDGdP^^rT2(ayU7=QJJ}W=v?2N* zBIbBobjc)ECF;Vy(9u=lQZWTbE7NJAGL?F5*#V(4aBM;!1SG8~xU)RJ9hfihP`Ynj z*q$Oz`vcO52_xxA>>k{-f#Bu&dPO#$F{cW_Tfu$O;88%f+7lr@Ky;p((2GXZgIy_% z2Qi69xZP0PL*~@2&mH`vH<!yjLS=1R?y`q1pw6H^KN6}UNWKY#t7g_zP3hO5P0ARYy9~k2pXC?QMmm);oh#w zgUhY2nC-Z^bh4iw^Hr)CY$RI19_ML9ez~*LJ851N!2gw8Ld|+;;H~L_;UV1ufVxEl z`}8tKYo_1?+vr13bZ*AUAazo>Z)IZ!;}mK;3a}Zwhr{0U{U?pv7Ul@bn;A{Dn!;9;^UuFv(GHcXq3g!1Y`5?x>1960Aa@2;t}l}AT&Nlu#7~<8yLW|9M_c6SO(zTV zXIfbERInal%NAZ70%*>oIq&Dm;_kYUgWV=hgYS0sF) zjd7!oo}Dh;NX?+eX_c+*$QjMyP}CuXZF)O?_Sgb<-uC%3ojOSo0F^_Nf&_1+W*#EJ zU12L3uQ^L-^p?w8tcgVE-q05;^ZMMM3Ol{UOKV}Aks7L`E$d$3t6@)aS50GJ+0I6w zd)4~O*Rs<|yk#H@uPhpVqLHU#lF$=zUxjgFFX{H6?DoUn^|zTUQW8DKk}{^TJ*mbN z0N9Rtw_tIbbnhGHk?akLA^eqy!H;<$F$72q0TM&_lQ_W7T!O?9ATfmh(=h~ySN+jr z{*@GnSA}?0h*$j?*ZC*+LcA)(t3tdgWNGSOS&@332eLF3vNZKySep7xbp&4R93J{X zb^K`!T(TtJ)p%yuG?y}kEomVq<=KDZ%5tz^xDY*mq|C)0xhm{w;BU=+xXEI z35IW5LFyb&d1X`S8FKfm_jEMJ%MLFn8>6ZN zv4RMoC_tUAU&5>+8+G7fj;Yo6TpVxNS+?q~%}9M^=-0>yq1wbC{GfrVx-`z;tn{p* zF0gChbK{e_CzSc>8HF(BI{-rL+9XybW?Dq-#)Yph-tvK}fIZ%-?4Dhl-fKQ+ZW;1= z2+o-Ll476$Nj=v;5rRYvJM16f-COG%ZZ+`SWGs=;=qiS zk?xe)P?;@J5PKIU*PSPD8U!nEb#^W_)a|GM#`P{TjTvNC26W4dtNy07UoUXrJcfcC znQvRqhvR+luFm9H39x#l@`klRz3h#lUW=t)gm+n3qdTqhxqS+Z+8uf`JaoKtnEhA- zK_4IPYJ{N}bZwu4OyDM*z~tI+7kyw{sLr(WQevl9)2j|Rw_bKX_Sik#TEV+ms;Cpxf!flIAjo zo@I=q3% zVX9e&Z6bJ9?y*b}JeOqd9d@^O8n!?K>vw}kh|dxNZsQ98>^WVXC`=kx>q72kkYFYo z-5PYqWfdw?v}xxkt?PU#rk=k8fLHVr3Ly*K+HtCsQ)}ecU!C0ZBw2G7oVm=sw?*FW z1OQN&QA_Yz4CCD}CTJ+KYiqg#0+0P*O+P(wNSEZ_mHZIuPweNXb{M~BJSk<+wM;54 zJ~hMjD6F2lX7F*8UXR0i<+vKwDC$Tu^2_Ip*~A&rsX;5B@Q%>jqF(AYyl}uqV|qTj zwPN;U1m%M8EAi9Ay?r(0$~1F3xE;s)J$%yJQ6Ym=?C-i)YF0c17Ukcv(L8BHNZ8hz zTa{rovpZJ^hyB`de0PA!UF%`Etg38Z)0-#4cQypA`~8{Y3tCRv`m#)_eRtn2OY4QJ zZ-s?^g<_EDTo2FM=ODof#i^pbhp;~pOtaip32Pv|+w>F$$iFvv88L1ig_<20(k7E# zmf!({%F>}TZ=BEtABG&^`Ef*tmz&3tUrI-jM%S^!UD8mr0Ea*`CW`>e#Z6xKBIuz+ zQ^CYMtt<&tO+_I#Y0&>;?;V3QYZf-$r)=BmvTfV8ZFQ*&T~%F1m+k7ZZQHhO+f~oJ zC(haP?L9kU;)}EA&qTccmRH2eJMVQz=9QUF+1RhCg+)8}_@#dWb9;ocBc5@!992$M-lXDD1G zw(*PAJ1I=anmD1C1zgJIXQ0DUW$9J0YGauoHvp(eZUr=KFxP+X$w>Qa=l|<=bs$M! z`#0tM=RO1mW|A%2uOPO?d4fIV=eVWm{=&QnxI4WL%`k@&s-n+3h9U49MAv1@I%do0 z$5jNJAD-&V$@qh%5gl897+=L6S+W8A+GfI{&V-28xt$vVC0MxaLZRjBr_A?Nxv}Rv z&!g`I_lFmjsI6k7YdMb3DL3v~-8=oT%;kezE7=uEHg<{W5+psoa_zDO0-4ebHL_th z3N~WT4@{4Ne}pRAKJiN>-D}U^uE*?tZg{@Ac4m$;quO!$eNDM}pQFsp|6O&G?!;~F#MQKaGqo_Aji?qa)H3vbMj zQGG~L$<-}o4)TEL&dN;NyefF{NQlKD&G~6}kCEqlxn0_9%4&iU-?usG8>Cv2H=#o! zHH=5egAo@sai=Rm&AbX|4o+%jJ~_^zX4&OAq6RM3y^&TNgPGQPut;7X2(T_8L0yAB z&89)8*YU3n)J1=aZ`i%kQ0lrhWx8wxYudAO3bTrCzMn^t#m026eE3dzDFtv#1BRvy zm_^DITg|CW-}(rNlQCzm4$hP{k41>kxvtul+njq1gyd!-@lcSFeVv)S9KSr=V(%=I zGji1eK|gytcgI>20F6^w3TTg?REmbtgcQzVUCm`;Q$tj_>`ved;SuJvNTttKeyN)RTzI z;1bP|ekr&@E{DOb3JS_@fOO2hh98de$KmanSO}*6{$mo8frMQ1!zeG!@xpwP9j9Ba ztQu&>^8g6NiB$NK-&J9+5aQkw#zu85C5lwEJlB{Ih7jX4@cNUj;N>W2g@(WNlLZ86 zh?}@idGUi3UX-dD+TRzi)kVL8(q8OkmGJFF4P%jm-~cDy(cQGXw3e*r%L*h&GpR4r z)SE}&IhtiRU`#`(t#4j?6mN%p3=JNmJ~m=jnxCVJ5OU3D3b!gPCFj{YQVgu?yjhT> zM9|*;!%QEw?@i`ob&09_!M`lGEyc^BUn%q#FZ^?3*l1Uq zl4msQ3&yiuhZ59&uQT7Z6}G#1-JNugx=`2o=!u0l7m{R~lea=Z7XHJFX#k0&UR-6x zt6ZNO2)x3zy>1Yvn`o}MSebC-wgLhlegFWpVgo?Nq|42Jk`dT{P5lB&O_IL#Z#w!v z;a|Vgk9iD^CaS{Uc&mZaFQ|$T?qv~g7JAR!II$!=`W=(^?oWri#vjhRab|e?QQQ8D zNQz5IS>jQ1UFdQ(b1l^Pt4-h4J|#Wd#>Tye7FNGCs}T$?T_Xm`{!S1L&V3^#HoCv@ z=cY5nLmRbC5x!H$O(xnkv~OA6!rJW*^aQ0v=zm~6Pu-a2`-@HEM~DYeF&K?raTZKM zf*db4QioSHY}3!#@^nA;t$}Tp6`?)vHAkLcQOl&(QJdmiN=9>Y{W)W%f|rYMyc|pq zE=I{54=xN8vy+vz#cgzc&_D;zTB!qRbmZEw*^U;gdxUS5cN(}Ymr|UjW@)8}Avhha z{gW@f(~-_E?3D5FnOs!jnLQ-$ev141QXergc)(&f4IdhwB&qmjgAsRo*x3y!bi-`A z{MzG7%{^{A>uqM|0?N~WIh3Dd?703tS1dioAadT%XwY-*vtZ-wOsb28Wwwe3N+pNQ zfEeFYaMAFGQq^v^LmI;{tzq57Ry$bNBp+x^onBdMksvHu5(^IPK!|1B1N_w)Z>bR8 z;uIE$)ebXZ@*J7y0PUWVw`P!E6$8v(cHl1cUy=dpSy1nN{)=Ql_x@o$AXg;mJO3t` z|JZuKzz%)8@7S>{^I%Z$qfC+8^~ve*H`)dfg*vb5aRjuUwn6&ffpv=lGxi)^l^THx zWVlA}5M#@!buA)j_f%vYJgID8J{%4g^PH%#U0||VLm6$%<3l#L(01c8Bo^ZG7GO3@z zAwgFbK2|)LO0fAQnrf5o*lDSce_%n!BokzG0#{xPu#}8$t$waoFhL5lw%A-uc{!PX z--m5HvdOY}7_n(`Bb6We2={&?_NNUe;M|C=dEp}Hk$t3OeE#_Hm3$nTPv^X%ELjx1m}BZrUFae}!$@R*teti)_9>rQ*Q(T1<& zEu*f>5k$owP&}d)H|0rP%xbmwr2CJe?};lSXD4e3nm^85XVxQai}R~H^FOgBw#X-6 zldS*jn7)D9j)9^z+ogPsyri;y@5lgJaRERk9mNE}&r1U6Y9H0*pJBG436w|dKhKla zymNn#ndA-^Y33Xib}Jp%^Tj>1jk&PlK@C$^3xLhfE$s6H(z^t|n6=={(7`ltHl`rqpNF7RO9%wP4qYd+`Z@wH94znK6=Ngx zJW3K7P96zC1pPWdh6faV2b;O858gGeJA*?IXfAV)Uamip3QZ-Ypw-2l-sG%lKzycz zfqJ>*#T=6ajY=cjHJ+}KP^pC2BhAuobUn={2(klvfNqktbo!v>4FIq*hQYWzfz0qv ziuExD(7*hs~W+Xe{;DIq5 zC~zBr^RgpC(66}rwDH_vSFk+@B&J))Z+6Knxr36BE({Gvr~(azup0 zi)QT`;_Tyg)fx`{Gn78G4!Pie=q?Wdj|?m0V8Y#>8AG1^1!97!6d8BAW!%irpoj`* zwdECaJmP+^tlwPE@^xaK-ZnZz9+IOJMdXJmrXReRvG(6*zTN9w-=R}h-h3YvmX4B6{1|7Qs{OdWAz<+nC&faL>Mi~mZ%2l}R zoI3Cv?^y0k3Do91MGa$NTV``R#c;avz2}*f&C9SEHeXY#35gh#VttS-jit=;So+C5 zKnbFai;Ru(l0atB$4aI+E?$DRi0h5OsqB_Upf~6GhalpvNtB)6w3AQzv+dMNGrZ8GK`|>szP@P=YnnXgoXq=k2W2G-lA|Q$6&x@waU0JoF{^ zG?{EOjqHAA-8+42QWHZBXGJ?!=BVXZUN{iNhQp(^uzkp$&-}Z!jnM`4M_S zHQA*kZRk9Ktf^k7%d(c2UcAPb0eS27Sxs7%hg|~MerW>;T(PPC#m9re!aA5#H^B@1 z3MSqO1nSGe?sY#Oj7%SZmN?ol=!@Q!cNENQQg5lUNwph!CuaU&{u$69Ik|vaFkf;K zm96XnULy}N=LNFUsnxK7Xdca}J-wAyn zO40My7Dc|VaO;4V8#+T_7`=Bjv{+OfDBQJaDg4-%yTOX zzo?vGrTw$jdTuBtOC5?8a#pbCo3%DzZOuz;%3e+2XmgFgE?~}{M0Ze>4E`x5pdVu@ zi(Uo3*B5VG%`xA=%r0;dZ&A3G-;PsYjI8KqH;Wv)WVi-1hdQMqlTFGR=MX&w3W57M z(tcIo--3h4*}FSY8Le$e*URGhn61h0je#Kx-8ZywEr;HXFD zzAmliZ|7TW@`t+$36i$_a8Q}9a>?*Rf+sWv@}|Z&OIINqGp$M{kO(UIG0XEs{$YX? z3eWGWY{>cu){p@y1M5JaIzc1t6CSkJFNlquNFV94Zr z2r3n55o5jEw`skWL1Wt#MqOS^D%>hK0Y!gSl&>}gdXK@uc{h>fQXg>j6Ia>Z1@Ln1 z`udD8o-vSJ@;e!^8v&AR&~G%8HL<&CsnklILzMlX*YpThqLe*sSu?_8XC_yHsuHM+Z3*XEkksVP%&EXeIM!X3o~gG2PP(U6T)-!V*~N+ropG-ALVI zq2f(3uZy?WhgNirgOMT+u7x3?;@e`~XkM`M;>_>QW4ygNS(`-MnFdGWPIo+?8e&j~ zJXdyvaa_r*(#`n4DqF}FhqQdO=2GPGSEw#BOpU_{S6vbHnTUtSXjvnhwP>!<9gT(` zf}$`8Z7~SWtbEKS*vdPH536+C6c@+CB6=u{>a*2Oh83JzU}<;oJj2=Gi_n(aQF-O! zQu6u~N9~pCl7^>E!pMon!A&OSz~wES41$<{k(lRf!nYjTJ>FG zwbiXfR+uI0y51?|%cnL<8q8=%pon!t2=`415yh`Zi8987QSI(p4OvGR@naL1NlfU_ zdVRXXZxHLSlHxd^LN+l)5_yia#kgmXzWh>HJP1NX`4hy#=Ns~X!lgT7z3+MOhqWid zkvnUe4@-*%{LD+4uO3^5QDQLKI6Xtt zadBsBWt+wF?B3<}sYYs^Q^9~pwqvF)FJ_X=|Bqe;AwfG)qO9^?Hojp)FBXO|ke zkw?251=l2jszp0DM1{6odf92qW37> z7VvSG!{shjWl1Xjib17V+BI9mzivfumlf%A5#k`d37U%e>|yWGFi~BIP4Zj~XZZpd zjjl0_6$*RR;k}gjvPHH*RM}q68OOyjY#UudH}#>-p$<8vBpw4{9FJH*$^m!7Y$4Xy z^qG;$B+Jr26fT^5(}F9Ee+zc-yUheEDnlXL3WxPf6wLx|Gp33xj{F^f{|>-^2jKrC<^FH({W}2v9f1F@4#59F zD8M{O(og=SrxXmtZOk=GJ8o2T_18ov!$&JK$eEC~^+^`jF;h7F9fSDr?d9;onnHoG z)3H>g=L!-usC}S4V4XVXAwq_-I4{q&Q$xs^xqyKG&zmqkX{HfDE*b9Lk|2kUD9k;a z@%Uzp(W|dJ9a0%g%+y7}wJZ{V+M{7+A?)XXLZW325CDM1n#5`>|9wQgHNHKtS(vKTB};yDs_1>(JIFTd<7&Ln`eY~t~mi2)x)TCN6&;8 zYst-DARKmGw~wBYG7pV68jIlkRRw;=HS3p^1-7i;8MF%3d(dE>((0Xnx6 z|Lb-8JmE#~*>oq%G=~^fSGyb%zyn*uN>}m6-tyP&iC9g+ssj1RF|e)n6#c3AMIyOB z9^~??M{rhCH$z+989XdisPtW+m}ooJMu>V&#f&5XU3@G0Tu&B1I4hw$Lp+GRy9zcH z!=HeG7-V3`&IN4R!?f9!F$Ye~EIFC3u>d*;`6TFvS+(aEq=rO_I2{jL@X?u$m*c@y zsvhIv*JdfC1^4#ORtzk`LfJRn+BT-9=ZjMFj#~(WSHU?@5)uf}2RK3N1ZN1mz{$mr zJRq`VT{K2p5Z3KPnuAc|hFVtdXCTylf+5)_E#$R`-=}pLpJMysp7l&-6_NMA!Y-h} z<7Riydao-xNOp4p3Dz7TCH}dm7cWBm6a&8Q#dbB2kay++%nyY@`98I`a=}mMePvfH z(Wt8~dU{RZT(+|60*?u-Eu8?H_Eze4z31cOu2z!g1Nd&ajT%GA-q`J`w>E`|Ye{IQ zN@i~tl5CNE)*gz`CErC&b8D%}Wgist2BN4ER^sOxun=%0a;E|r#|7g_(1N`;Kf8g4eBAo6`-UMX*uv1ozNS77+wi++!I*U}A(|R~_ z5HNhj(ItNOmAy|%F-e6cI~bw>u_269Z|JRpk2zO1{Boo!|CKn4C?>hfq4XYW+6$ww zYwmJ@;P9Cu_RDzH+}!CzVk#}G!VG|*m8?zr?VG5``X}hEK)sk3O?3F=Ks{j5F7=|#2*s~e`N`@Hv`j;XZmVcEVzRT2Lgc-SoCv+Vfzt>MN%PDikD7} z!|kuF>{aK9;aZHF3}G&nOE*<~{x`VWH9^Y}NeJW_?Tm*|gjf-N&41u}9YiwKU&oK~ z?CR`%Cx7OM9sG!WWE$5-SigYS9STm@a}!s(hO&(;B1sNWKQaglfBB<0ZIEY0wUIq) zKN+i%rp2@e1-FCF^UOFS1e$XuAq94TH=bNDoH||Z{HoGprALeo*=6aNzpoE(V;P^Gw6kbql))GFaVxr_)lef z_r5mjVdL99H(Q3(0}QyYqa^^QBwa$y@o?Yo-aMj9nO%;Of_9pBVQs9V)!{v-=!H9L zfnVoWKnsK2aR?+uhepANDf@?C*>Ff7C)~nNA+Npz_7Qs~nY(H=O4dvDXTJc*91K|U z%Bj1M&Qp!;7!B`N{Iv<4Jc;PfX&e4|>9Yi=Fwv7p8JIBYUx_tn^{a8_s!|dD0FV#f zOEHRrW@y;uwP*uJiD2Sq;MhWu9@uJN6J2pB)BT2vb7ul0!qjJ91q!a(J&K0=7=+KEgiX1Xlw+TS!iO|sAuO(68<^=YK(v~di z$Br5B-Jm{272bK?plbIGTb}G|1q&f`2=B`Ei|8j1-Y!%X2BaFxima6Y3P?so!^(^# zW*I%3i{S|bx8!BL#H~yH0YTqw)9gXhR&ku_$fy@xkCl}TfX?qhV2#c4vD+|9_LjTY zHXfz)_CKku(G&`w+5i5YmFJR3<%}5%Y|V;F3LG9UXHas>wKLT?nX&~MZeNHJh1m^5 zrz;uG!ZWoF#$|Pco~*3BW+6kQY~~tgeR1)Ln0Hkpg5B}8-I zOcy?H{I0;{(hLX3B$$#pa74s$&IXGe-Ds=03Tm(%&m5sPz0)4sq!m{K0A!Y^U zK*uyQf0W&bbY;>SG_1M9vHwAX8+=fJY+G1~*Pl-;`bNjoLmN{8DSDUPl$Ef1Yo53r zh34M~{xsE~;(y4#TS(*b=j!q#X*~)&{p9nP`J)opvrmI^@?jedE(Z$mTsuQV2uDKE z`Ux$KW6%U9x}9q&?0vN5)Jc$Q0!x}aV|@Qc=Xnirc!n_b0L?P>2hM}AW$HIp4pzUb z?L#y(fdPE3Q(%91Y~%ao!j_LJ7;x=5@gS!qP+vj(qNM2_TJY^C;YWAGN|6b~EoaD4 z78dX+=Y+9M`n$7lISJ2A(@p(2d0mxMhUseXeH15zsfHm_h*$B227B7!wYnSs2H4lf zn-o-mF=n4M!QPI4`WTKTn&e9z!Ef6Lv2q#dh&$wn;#YLf3OsLhr{x;mkaUsqB7#Bx z=*q-x!pSBTPKX!nMzRccPgljqgKeRVICvF?eGwhMjqh2#oGc$P3D)0I8aCCOy0e%8 z^?voFhwI3tH()S0ARw1f%&jyv+WVBMG-yT6<`q3 zjDf>4*Yx_Q1XzlnJ?Fy<`A;s5rDV0<@F4Kt%msw1(dS~L^}2E)rD=f001(T#F%e;~ z*#8=)272|6It(#Fl798S)Zrj5AsXFzY?m7n+?6DVxNf7@28tXZ&x-Dw>gC-mM5UUV zmSY&~@1z9FXZDB%QAP7f9WsBqV2nDBZzKC3q!ij;99}i3O%QPPcv+T=ngQi^y0e*+ z&Z+J(RIm=ldi26>PIb2&Y~rpU2q12h=(W+>23R68Mj2(ZA=C0&lTA;D(;WpZHvmq2 z){Cc{A8eRmBb)2bdVK_{b8W@f=BxF=r?xuf{xnHk{u|loU=uI)R1zR5taTYB*PS)_ z{)FGEn>M~TV>_8D;W(NMDu(({z_JYC!FJua-hboTs8_LuD9YA+)E{MKSk8fd(re*(hq!m)%R???BD@j5ebt# z)@zc}tlUu3DsLADuV^HZ^(J?eA3pCd$I6?%`JfpT9)-GKbFHxmvJBVW@f1W%#t(or z<0(Es(6y}YyuMc!kU|7})=a27D7BcMhk}0wegz7y0|I~fD9(AWE5N82}8gx1m;(&(BnU_sX}6R>E;8FGP-+aE7YYZ%Jx}Y z>OH%?v!K&Mzwt^}+0^mf$yyn#iv!JzCVnM`vNp)&t{K|bZf!@NgBpz)$Kw>_#3s!V z_>6>T>H0Otw*-E-ANW*o;tuvJnJj|7RunU3qns<2U>Wioko1;rT7j-R`CjI@BhQXW z{d&tf^0V=loe@7No^pdLj2_pwn(a=L=tYl+ujJ}Sqp6HuBlKnhFtfiH(M>j@mhM3( z!V9f-jfBc0GPhWrrkneBTP8FM5u`L>x3cK=Os;A$yLO>*5Ndf`9+#GBTj{8od;^pI z#}1WG(MY^4LA$j~yJrM>W)lJ1NYE?SGBv>6t!S}h5hnGd;&#)vd-!~mq0 z7Dj+2EM_Y!ETYr^!5K>qL-0bakRTI0eCVr}UQKq^Y9oL99`DmIr(g+`vz6v1VbNI?&=!CNC5)O49Oqn)fz53G| za+&c~GjXcRLkZJM9!B)QC_0m;f@ReQ_A6!jdyT0o$$DZ&LpSCg_zuG`JgJ<{1+4LaVu22o@3N_kD z1b&J6@qAfi_yJ@2Oq#rYt-;0Lcln7>QN;NeCXGOywfdz(=-d)yDC<$&Z1M;@Kj_+^ z_X)i`Oz3;B(jkL>UTych{Ycg5#V*(uuMXSg}CN6)R;2VE18n|=3`{Q1npo!ex2T_ZQ1*Q5LR%^-S6Ct~T@O>}7kHd#9`Q&tO+usW53EL=)lvukAs+pRZY&wWFWe~e(! zfXZ&_uK~tj0KBMrJg*OtC``tIFCD{CRL~) zC{P>@GO%8gbagDF1TrDx_*fyh$pSLMtA34->(<}JfftkX`7f`rg^7i*K@(wfHs<~e zybc9(E{^&u?c?N)ru2nyJ<)p>sNFnqEBu<8=5guRR=3he^=eSzl_8Q{e?elXH}$sM z8lcT_-NocboD2a``+C65-UHTI+P1er%-@j@RR4CsruQQvgd9~nefKO1hQxi~)51sy zo@;|dQflvZ)|WxG#X*u@Fk`+%*ou+u%A z9Ukv4A?VgTHMSver1_4huF5}dRu>rzqd2Wpo;9`xZUDx2Nbr>#W)fAIybt7JV_Cij zWccMY;Fk|H&NCwI9h=|?aun8234P<(s}!SEfUw{vi6L+l>ru6H<%y0%G(cu?$T7%v zB8BX*FTN2^r)@->v%&5`95wnCV^u|t84i_D(93KSMJP>E1x1D>l4OTS4N-~>*U#Bv z&ir@m*Cp>{1a%AuAp7)~pcIp=?mYBasw$#;U6Ve*g9z06!|KNx0_J()q&=8%AqKsN z`-sBHjrl?spzttY3?*J~!zGOHi9osg7|O#2%6Fh1u)W%nPa+%P9YFyaKL+u& zOewnIZ+wQHf*t>GoEWHrAql4WPW5O&8AGP5h;64}MdPvsZ!!Xbho8K`$arnX@-NAm z!1vWPf=y>CPc=lk+@=LxMFmfm*jVvz)TC*jrUgO{HvTJm1-S!6^=v9H;Fo6$yi`I0RWmuPW6VH- zMrL}P`ZGDxKY5nRzC}Qu5iD;coH=+2>aDc1Z!wK;Mr9skKYy~{c`a(R8<(*qYeW?Q z)PFeq335eX`jH9Uk5rQuU*VGaONs{Fj&-{MM>-^cVDrcniq8ThQ6^4|a}wpwGPvuV zsUd9bm#2jy@sRa>U&DIrfIHfJhifg5L(72+`2gssq9Di=>8Hdshznl@>M_^UXge_HLzt18l=ofBJw17W6nc<3++zE`~* zbCm(*JIVlQmVKS!Z_65(5q~n=o#0!d zEC|Fn-8B9zLA}k@ovua7@wdSeV*fs*#vBOg2L#>>0)ZRUaEYXHbi=$*spBQ+d%P&a z1->S=J1qFgFfFrC-;W>fT@}I!CrD-~;qiaQI`-DXKuhT13}Hq`-$jjYFUW z2OftU?jB->A50y|1@(fh{lfKAVg>aIr_!}>5zzakfPz_~#R&s;s$fP7B5`{ltCY=y zu}B)rqb;pUT0uxX?%dtZFxG^{6O#Ba*KG~$Ucb;50QJ?5zO#6&Lie_AGudM!_#ts- zSS)|Wb{FJz_B4HAR5Eibs}6nRWN|*^#`j}T$-m=gXvgyX)Eyy-Ef&#mTA*sIBJkD8 zMf$=O-Bp{<){l26l3CeFeB2-Ptf+9=G(~M7lHKJC76e>drQ`K{2*dG!t(8pj13Bty zn&~Lk$+IUf>a(zNZ<;MYB0qF5IaKqoUfJ zV)KB%9TYP;mi))7G)FEB_>CPNG^PziD}-BmPLCL*E*~^cC9{v**)#>^^)!413=VlD zCgUGN^Q=_=a`C{*S0~uzx}T$H$@-)3*Vu+Fgi)ZKQ(o`IKE{&gn@WUoDAXO{ zvVh#}iHo`ef^h5200}G+`}e9LZ4R&Drxv*0;dEWf=W57aScSCWXzSHB z)M}+oDUgvd+G~K7*{3kYw~o-%ADtE`QZDXAy}~cga={o3Vi48tb%}1KiD@I@Q?sDb zz}8!tUR-+igr}5#UT;RIPV%4{}hc85E5z+-MP2%vm4>G z{|6n;x~xhI$ih7ApZ#?x27>iZyVYl*^&1NZ1H1spMsE==HbO_jjdu?t*INt@_%`<| z_8lRa=&yYI0DUymA6!(Bs%gv(yp0s3t3{Fwhuw$!at0hl-`qFzRqAl!`Ja{6uQVzU zaiVe&w}TWG+xfH+c&oj3o`JR4*g&W_d{pkizQqk1w5cDQ_pxuY#;x1i=Xwk(K{LX< zRiW_SC!bQ+=8^y&>dzvEBFVdl4k(7ebuyl>nA4ec01-c_wq#FDaGta24@Nt?U%GJ4 zY&TnlFNTW`4N~)b36DTq&qAcFh<46}5K_xAd~VaxYL8PLIN#`@!zsyzKrE^Zg!7WU zxBCZ+EoVs+yJ>{VAA6M-+FfWfg-MF)MPOt3?Gx}z_fmp35&vOo;>6 zN}L2Z&X;_-(3eMFHx%C?1OMtE0Cr-9wD02qBX8k=z{j6Nz%LNM{>(_a&02~-9x%7S zchI}5XcA*LZVkzWX4X)3T=JkUqP{l9SsRH@7qCbTx7DB|gn%u$VXQ(cwll9jh4*mZ zAh?;`FCUhc2`WJ$;9mDtTdhn#*p9n5&qWxze3C6vVnLy-P9H&ww+*y`oBO3C$RjW{ zs(z>?upDba0^qJCJt1#I_IOu;rxxux>=-(Chtt z@zwA6lKx?R1T`+^CcEu-$3TWs7Qv~QqkR4u%{Ux; zQng99w&0hUqGvY2Z+LC2r%DawD)9w7ke^p5-@m;*v(>!i!e(|VP~W)L7j8&2D}LO^ zOj`_iroX5_T0j}NkavFl0LCWOIU&wyan9}uM4)v2oatvHHpL$hKz zw1Cv_Ox|01zW!kfXj}_q#o~?fZ+5>Chq!%uM)NtYHZp5viQ&+G3+%wzn%OS`6Ty3~ z^5y{tzn`r#uWY~sSGI??>IS}*7=Z8z4g-N_cSh>kK_cHFM&SE5r!BiPko|yXYTV?; zM%b`Dl#yKCPV@Z-oF1k&l=Q=i5FzPf<_*2OacI{;Jighku45x70!SR9M&inSv{R_E z;S$IRxwu@NU_TuZ*O0^AK)(DbkfV=F#~_5*Iq)tKIP<4I2Re<7;Jyz1j#oG$c!huZ z0Y@_wg%n!8Rm3=-!TC`nVEz%NINFGxHqC*ut|f}}lbtD~y$P7fk&)y0iHTVum=<#I z-CpE!Xym-7v6)5YR(UwrWw{73Pg_QZax4~o5aqbXTapc&U%ylmfB7dF(v3*qh^So> z9i%Lt?%hbKE@f)Y*>8g&N#VnCN4G*5&JA;ao<@sgn^8FP_?@`N1hLoG1f*?pX_`w3 zw^sR{scv1HC;o@;kW|SYV32DZ*p7-8vM~656n+XN5qs*BaI#}w2_4y~Ao4u)KLAe) z+gCZ}C?fpDrgJCN$s8uj<@9%uS_}tb5 zC_;^6Be@UT&CC6V^Tlog%+@F171Jv&g*Cuok8O^tdbpUJj@ArHe%jqcY^)2Ityu8A4DgiX-}t0JTzM86_Fu$|$39gYrlzYJ zlE4r7sm~C&vzGcUl9EzG3>W=2@`8*gDp1p`l4YAUU`kzI_b{!{e90R(hjWZQJHAp; zD{W$$)dHubmKwh!7}NjJT_=}|`b?uRLQhDxu-8gC=KssHS-){*{?*PXc3(tg5d7|& z_lBomT_%aFG_~cSxmKcFn!H^OwR;|zz^OTBvG_|X&qRPo?75}kgRLS+L*U?;Bi7@# z&*PMpk-~`aXeQmoM7Jh_Z{qx^W```9BxKP*#(Jo!$8x|?0!AcY$>2I1(ZmPquZ1g# z`Dm*hS4G3J1=d=ecu>j-qW=s^&y}d<+dLp3fdEAW-;o^usOLK^+GH3SGjeA%i~k7I z>S@qkRA_6soJi{Na3?Yntgt5`{Ry|29=ToXrnp;gFU_{w60!V!oqehVuD}+Wrrynj znf|LqSdVE`{-$`Z{@&wEL{inU(+S_*0`7XkxdZZEgwV7 zIEd>Q(|jtb@_Mf{DE>cx(s>x*`?ldRY)SbD^q}bTZoNbBn8Cf3;gYBiBtym1fYT8dWhV4N z@`HJ_iaA*mDiSv7+i@G4_WY(AcX$YSPc_C|?3{@@ea3&Hcm#B41|i-VyHR`Xm0S7= zlH4GTW}u`f&4-Rhr$hRXt!OM@D?ON?vNcE_bo0PP`{VKv<;^JQm4f2OgYoe_) zgMz*Dt9i^vs&x=uMpEtk*lJTYQnjVNZFRX=ps;Ld-;IC}WO#X&<=}*=Q-R$EIq(Xh z@+Zt1y_lK-*I}a$tKu46bp{goIs0A@TxmT94o-ne*UY?B{Y2rMTyIHw-*8khTDhct z_}H)%acn8YXwMhDF3;6Wu1L1M1p0){0RiQ9bSI)c?eo}I?ZVjomG+3TH^bVC@Ml`z zoSl`nz2{G4SdL1876U4L?%&RyKUlnKN6YjNtY&O2FODFmiJ?s{8&sOW}=(UVxD;gzMeu!x)o^w={ zuxe7#fbxReV|OCs|8}lRQr+!!dZm$20RCoZQrs|Fmj&gv{^Y4GQ+dWYTAUf4pK;`Q zb3z4Jkq?D}^~Q(bPa@w$m?)=L%x~z5seSft5x?x@dRcs+DEz)!LI1Sv>!;4Eb+lT@ z_DVB)MIIkL^@HtMh$*%Z?Y5r~(b?YOPyTGMY=(OY8W^fKKm}Qu5*P; z;*QaR*qsms&CCMhF7b4}T@kvCd_;X^n$gFdOx8l247d$Psc*?r^w`PXn83)@ajEBJ zT6!aIn5X3W9vZ9c>NR~(gjQitCulDX*68&pg}+$}O*4)@vjyFsZS1|Js{rv={kjc< z&wiq!9heV5-kG(vN>15G_F2b%b@4%kRO-OA zQjiR%8Gx_({A7RA{}vdx>t9!uZ>(hs|4?n+T(iJkJyY(&!u|Va&j3w?k!^+s#Hl|< z#rPo2SIoIf(M*KBk($?v>Z0Lm%rMy3>Kb61k$hK3ad15YdWJxw)BXkxxmWm# zpFth3bK%+J8FLUZDf{TqiIKwBg)7c0YaMQ&tT(HRW-WGLTlfBh`VgW@g$Vc_!$9(} z+IJ5l=Ol!!^pwbC95yY+(*?uU(e%B6)vuRSj9ctNs1pa zsU>TljxOgWXBJR1qnVNLnrPuEOCM?Qss)i;CugG_8wE058M>YfMUpZxO4d1k6CP52 zgxSu)(5CeZt|&YKmpfn-el=Z8`4t8#gErm!tC>F)vu^~Zz#7do-R*cg>7Dd9M7yxa zwFJyQvR>o_EB~@_G))66v=fHhC~o}kiHhkq_xacWFMe3<=n9qLRNZ&MB@bE&o%#Ov z(k3wRr)6Hyr>3+qEyx^(H=8_b_e~@^ufF?mw++2+BX)&R7kJ}^FmMA(iH~!UKi}80mOM~tWnH3)yLn{Q#V@nq2pei(LN``?-m4)Q(Z=BaW`R| zXf+N}*jhdYcY7ggfZp-$V`RaqlmEfqTg67!Y+Jf!W@ct)Dl;=PGc%W&?J~1nW@ct) zW@dJonc3O3&(S`uJ}tFcx1X-`zs!fVB9*C(6?0_HIpT}JX)|R#l3|SYE{$;c|tC7)@_{#g)KOcQSz=8?KYLi1zVxtI;wtQI=S6@Ke zK-phv`9S4`F||<=EYb&xR`N>q2nB_eOS}Um$Y#G8dAqr#>3dYEtrX%*5)n709vUID z!zO7Ra!o$BSx)n9`SFCYpEQIJ*-TsvDYBXL z5Bl;OKdy$e1PUvR^^iny@tSUOo_XMvm2P`&{Px~AN7mkl7oP zxKpeu!ktYgjk-0)!_uH=44u$z#O>Oswj$0M-N%Qgo}1scsp8n*fL(@B3ZPQJ<5N!6 z($f0p2nFRE?T-67b9bb4$In_u53IVo-cg;#_) z_v;VdKeDmeMprEDfcsF%jiw%tuGJ5S_qp69^e|y-Xw_m_*WNE|Fjx*XT?F@KE++s5 z8sdp-u1MR274P)9*G0@(Srji=TJP)#pK`Z<7lQ^*n}%N{!jG)`kzkrJri^1-E17iN z!K2j(XQmPlhvtDAH#(`bhVFDU>`AJ0kH$qKDF+KO*?wR0=mH~Ear(sli z)7S%ws9wCCTikg?OniiPh6yVtYyK}!4TUXfvZEG9 zu#`PIa~%+(C&gva(=8a)fZ0gWqpBkr5-xU-%Jf(p!iyg&0+0o}KG^OrFlBR9D+&%F zk!L9Actr%*S*OwhQR4*-Y7?Q$o2*I#57*EO1rH0huW9aK#uUjJjgP%d*f|m;37E$a zD{7`0U9NyuaE}dOV7Fx?ebemCJ;xAG!?w7nC1^#Jx(z;8b?sjD-KH^;yudO@>CEk) zg1z|9KgOFB@jcn88FXMBj=~pmJC#j`;tJ+3mN-P!?|gQ(0zz>tXZh>&{CJ!z-jWn7 zx&NL69v6pkGF9%MQ)I#-BO}7uWKcoKR1S#1XOyl;>N&w z{I!?4yXOC6XMfV|Vm;fd&>=u^|Gc{ul6frJgIP9*k6yP(*EqXzld3b(BPhja<)a=n zl6#tR+>DI5oz~6q!_fvFwI7_d`^0+UE_jn74;c-?KWL)Bouj`}RhUdRV#)c>`qCP( zET>EH0C*(*pX<>M!iIj>pQ)c|59<0ixPa4A*R)g+X}$8c(sQh@{?d(kQ3iqg33&PiMobNhA+n5KsuFu z>k0nb*6=Ts-v2bKf&L-Rxc_g~2JHzaOWJmd23h$6KnZvK?E09`+R(V~69UHQuCwsT zJ(T>7kvOL{;oyX)AhNlFbvfZEMAISxAq?Y1I3`RVEdhQFt?(nnNA@241cS)-P`xB+ zARZ_zF`cr}xECl@cV92eX+Yh%kl{K0qBA4@itZowHhvCJQBN8-z3-;knpY+CovX&FF3sttJ;K+Jg<|eP?# zi<5G<+RP7zN>BV-HX2$MX1=0Z%C)*wqxleX5fVtPuH4h|`#bke(wZ;v83=cmM@?Z- zmk*5-y2CTGBXsoLWzTR{edJx<7c4VYnYsLH)lVflidTCP{7)4M_(8`rnGAR{8r7>8 zz0FRM?OsLSW2-g3`=~CkrbvGeC64pQ+DBj?T+G!`RE0ov63HUyJD(AN^cbr%G%YYZ zs=!!)ub93EKK#zK@`7c@4JKhuap)VRf+9&l1-z-YEUJ*=nUtwDCj>mu70g=B0*dP# zFb!;{^*+A8%c*($VcF()ak5acM&taBg4}Ae>0G}Z|A;XCnzNyyM0jX|#Qqtyz0HX> zwfP?2Yr=4FB$lHLkxOBoB2a(K0WV{kWmK&A*1yGmqAhgz9q|GlAH;j!jG~pe8az3Y z-3-WoGr`mgNcFr+Y|Jo8SD+0R2#hH zb)&bRKbO{wh7;>UK8yI8`%>f|Ta_;TGMPU9YE=S4w6=K$+B`@%_{`}ai^)JlfEo0; z9px!(e!vE1e0d)VcA7ZqL6q5MDz=lFz_Zj&9t@gmo%8*H65pg=Jo7ef&czB;8Y8OX zZG4x`cLA)_fHS#B zt!lMsDefdq3#K}tgC3D5EKujl25Dye%Oe8!^c}8{xmeBa!_rr*0Tf%RzESIj~rY?$+^kBGn zop{hY-cHmf&jdN9yeIO|Ow^$25cMwaepei>g z%?^RpDqTd7Did|gl@aFn9i9A8MSbF5F4YwmEvNHatPU0;c5>=i@cdDDFHP@( zQ~bYIyxHHi|DQ%CuzKQ*$Ny!u6Xy)`I=xlNu=;uxpIb3~hRlO9*V^(K+d5bK*Jo{= zOku8LtQ7E4>Mvpe-3E|M^T$tNIP}gtg=wN!#4F^sms!aq9WFeZym7F^Gla~Jeu`WaSB=ivtBU z@t!E7D>9G|Zh_w*MNL}WTl*UbRyll3M30blu2IaJBS)G4^05@>n#r0i=Eom05LY!A zM^uVEHYx6JjLuUcx7dFZW4~j?Ly+!SwK+D(*w;H9-`)Mn`;&%oKvh%gyLmKiJ_cGp zaU3SBi>#(yc6*>vJ^|7_onFy#@n3U_7cG%&P zPB-i6eKUd0%R;=UT%N8d@fj&2nD}u=0|hBAyo-y*%r}(4{)9{R+>)IWnRL0KKZ{QA zPP8F8{ZRtp5MM3!GAk;JCf>jMbL@9Khj}u@sT;W;_0^-L#jjcG6mr*xQp=5mA_s4f zvCPI$)a!oLt{(Au&;stxAy`o7RYajG2C?KN8&1dK;o&43SJfdkVF!2~(7mAE`1~)J z6SoAlbMLWn1}m3}tzfFF3!603{cCk56de~yX8~6o-LWu9CWL)i<1<*-=h+SX>`G^0 z6m+x(d>blczudzk!a!l4QrR^lPcJ}qdO`JjVYPEukZhfLN00}im`ekPy=Oi|t9P7r zJF<{J9}L_#uuc4{qD8}tHM0~MURs?6NT&l9d5N>*i(lW)XeU4XzMk9&;ODEk+FN16 zL=*H!rnTG+cvqxG^~;U+!9|&9=LxINr*^Z26)q9(=PVNO24Hm8cu> zcVpOp5`UrF{++tOU5PWE|6A%p$=m9Ug|4hrt$D0koLxGL%l&0YQBl)XVzzn6ppqA; z%Q{{`I{D-Aj4LJN&qV(o5v1rA75*1$G4(7as_J#etLmF@Kd3sd014G|9t%*?5-%yPT4WF1hd5ZXItjb>OzU9r z_Z8tAsKlp218~_WO!Klgo!X${ z^ui6j9~142LLT=@2B9+KBKu_}KxoFOJDt9kxCCVCh!pI{8-O`FXm$^Aye6GClkZlS zeJ*UCjl`&P^Nzr?GJ<&*N_Q*ASgZ_e>X#NgJuY*phC?(5=(Y=R*K)20k0>?7sKomb z+sY!A>PbTy1)&A_Yu`r%y>o?bjs2qsdyp#$T?&_Nw$Kvhv*NRRI;WOhT1Oxka0I|} zofpXsOpgu>M6iJ@t1m!UuGcUYw1G^vQb{J=C0R9R)-H4c$!fE=8ADNycxRNS^^xqO zC9hIbrGWw5#3|BkGabAd&ky3Hfy(YT2yh?tzDmof=NC2#wFvLnvFc9!`%xvR^W{lR zuZJ=-t~d1FG0bq*JR#$|up=xv>GrZZOR!90Jwwat8G*;K7Xct)!V>dX;@Rbc)Uiu24p@Rtw8{*2yYC&OEkaBiG^|$>Km7QR`IUv)WPtZd_-Zbz z90cfgg~@YY!JalEd8z!+&u}dfwcQstWZ)V>vb9ul$stO!MMQg7>mM0T7mjF=PUhRg|WP5e4&WFd$r^g6|9pI zgyz~j7`u}MnMfs4_ex;MLIa%2sveogGPrg&!3pfPeF(1WXuO3}B|X6<-}Y$YO5{El z40xj1B*@zyzieHuRlTZk&)UDo2U!`selC#yXq`DEgQL+&vZd4=I9)cMTjcA9f{4c@ z#=h5GjI53K&2hvQ5X>CO(Pao_{gt6#wA`@KNJX3l1{;y`E)M3wOKC0;pZq;)7QiPJ znTWD}(+RN2+m#F;z3VQ;sqHb8;YDqDK?L3wu1R{SHmF(0Ch7EbcvRZLBc2IqG?4H; z;pqJPy?wmNxBmHQb`byF;4D$ioMivlcKQJ%3IKfKb%tdCldRB8drNuk0>0n6OGI_q z0x^j%wdZB00pDl{;q$++$SE3*Q;`V)XD|^)q@kHL3d~VPqXA^s6?E#d5f!m8umIWL z-J`mw8>VfluNGnEu9BiDDuOcRK$aYOBolj z1`4{b(S#1q69`x_yeh1WJ4|E1n^^9UZD4^M&jjfX@+|{Rob}W&redk2jQ%_+>P(vZ~P?%QyC(vz*@s8R7c9z zm)h>4RF~D;7lwlmoBVoE42LFgS&^a+T&|Dk&F!mXLMAYjc#a>o;%%1qeB6~3zQadO zv)&b*eWmZJ)Z~$E?zgqHJnIt5ePT_)!(G}DXs^z{#fO+8lUJ5nJ#&5M8V>F_`y?T) zDu}8orQZ=1^a?33Hp4iRC_+yQp?6Hvr$RkhzdKsHHVVu2 zQBZgNS|($6GrgpgH4vWqm7n*kA07~JaFPDR{tUySfQH#pJE2arzZMhY6>3WZKYDIH zvds45vqz*2Geg1Br5NohOZv&`IN_o!_cZY7B@ezw$rEIxQI%-8e1I%!%1M4dg z(&nx2>{r3&%76p}vYtSl&eDY}v$Qi2{&$<&|AgrSq2K<)5&FNO2L112{^1Dy!x8$2 zBlLe@0sX(+`iCR*4@c<#*BqgLRP}#X%>SD!|ETIes``(r{=Z1)|KYX&sOmqe`j4vq zgQxz#p;G_Xn1Arp|KO?rKj5kVt8lnWobmqO3WwSguBKOZRb&~mID`XMZHj5VGvaBp zl~)3`VaulnaCZf)d1@v;3Q$0Z{XS8vK)L%X*;3KQ0skso(H$D9f8D(T{XIQseeX(t z2TBovQpkCGVPmWd(&E(lQRVtgKASBdm9=NUQnusxnd0=2K&@KWmDAw47|NL1vyu#G zSL;cG`-i5w_=Dhc5!ns@6#$W((RlK`R$4Me-d=5b>c!)-%#XRuM6XJdj~cR;>#ry0 zR%b}hbsHBEn}s@dHGk)Rws9JJ%POU`_9=?dJg^R)3)AM3l zit|$>9olL4e_@!TgU}DdG!NcO=87ztcLZVkD4z{I2E2OfbuKx85Q?)N{NZ!kQ>ol=`7^U-!Mlg= z$=J5r(c;KsY@2Ji$ohs_^vN5X@iI6tjHd+5aR?C615lq*Wf)ts{mn!%hxqQBnv&=9S zPkHkOJoW42W347L!xo**EP#+~Ki*o2tutL=4hS?_j7zCtH5p7Djh*H`J%;RAR*O?v zU}xm-9>A1m?NcC4m#8RGgydTFXv2$o>luBD-A(mHA-vj)8o7X7y1$#|0c$mB7dL@? zVk+PM$wiZozouuJisrONgiZaKj}S?6A0}LsW>SAq5MGrt{q0ki^Asp(GjJ3m|Act> z!Ps6XB(=dJ_s#*acJZjYrG~qTBB-a-bHwpcFla>Q6;%KC^gauDf_~HKa@mPBS%DwdS<&lnqKkFPh2SqWy=8i+H+sza$ z3*QvlVh!U;jL*(G7d*kQ3B1D#f_J6@8jo~kWZs9hLdXaBw56M*-!Y@xjlAvpUp8Of zSc}g;g0G@~GBZZt%12L1ZgZgDGlMT*P=G8cqW)_|0q>uof$;Ma!59~?-2tWvQj*RM z-7R0u{>wb_AH`yezJE_MhzW7V_kWva4dtT%h<63o2ULIs;An;->pS2@HaLl_7IrQ5 zM2=fEGXF{~=8l&L?p$VmAUdbS>gWj_jWQ?3W?uN4$zj#d@zxfW;8!^1Nf_N=0JsUY zI%G^qH@2$XMqmuj+9Mo(=8oCSV^QS&AT-o~aSv5!vKoG%Io{f|U2_T!Ls=CsCyn5X_yvdetj6b}fJ1GrBoG6(+ZM|vvDQ0M)mNxHe`ZUg z^>rr+jgpwg@bJGKE2A8IS9@8V{9#M8lw*lwr;~k9P*QsD~F|cO?!mePfqPtaIpR+s@6QITQtlx&-e8mX42!9c>-utilwx z#+&h*h0~=z2B#YoU4I-3jwMwhehO1`AiiLqFba1M6_L7ykn<-Q;l8$l{@_*>%&gBn zxePAEveuySc~p(hQ3H9R9`{lt+>@|_pPC#FybPS#l*Wl$JMXaMk3q!jmm0icsiUmM5xiqjV2Hq?xB+*)A&9{->14Dd>+?lW|ve_aIq7tINH;9o)SUjg@D zf#+YL?r#9$`d9ed*#h4K0)onw+EwH=G*RYF`0WQcT>sty5?qrv_G=I-FkU7e^cnEx zQR)o%JMizDIE~>grnJns1;y2Uf6r8E81jAcPWS!m79uF0s}8d0dd8Oy`o?97%hw7l z{BZda0xIxx_3226C$)kkm{S5F)8?p3 z@eFE(rrDyS?^#Y28!EBfw|7h#GLc8kJ?JOl3VX zW(xvvmV_OxC5Hw9C;EM+c4+nF9|fM_v<+?|3p&UJ` zW}-L;Zqzmu*X1+DHjsS0{xYZV``67~DR`78x}%B+mOu3(0q8`x8njf}#B_<>W1E%B zS~wY&;XiJ^oEC0C1!(jL_138Ti}s~A@w%-lC*uLwm@2nY<)|Kcd<-UDHK6wGW7ESY+gChDC;Y29GVOi!>|NgnIH z^pF9TYDO}ZYMeT5Gqb`ma1@{#NqJXI)2j;hbs?B4_XO6_6#DfF5l&VjOaH=)m(k6| zr4db;-(B_u$8U&I3*=1%QH$3Q(Ted~oY`SPIS`po;nE&DhIO9`&hI^1qnD!y=Ucf# zbjclr;2_;RXI~OQ9kE*ZJYi%L&@BFbH(7q5sKJ?(umT$)#ZN<2rKeD?|CGq6WW3m9 z1L7OQnf6KkKt6y6^63D}Wct?KSwpWh#_pl=mjf5KrP$lz=d`lWsh2~-&(s~}=1juA zmP%47m4=+!YAZFXd=}~3r;T9klu~HN$`)SmUCKL+IiA$$J+hfg9!YeH0x(de?&(I}P;#;N+ ziJFZ>A_q``yTzu_p`Y?Fi!T;2o_X{!baJFL{WOLwncnS~ytUiw0jchQT+rp#=Q!#h zY{T{!;zJWWjOEwlF4;peUR=O3agQ6#B2!kwmhT24BRGIEopgK~%8+OpfOX9_*WGzFpI z8+~p5B9%L6;e#q~LYs4z0oF*<^8I$E80xX&2@mj8whEy#~9L^P(qtG+`|{9EkVY^ES1i(eG}^MaGy z&lEX9)q${3>e}xbLjD)-<#{)@QV)g;DEUbqgDZIAzU*RM&D{IX>CEgd6`SH_o4mSf zaZbv!N47fAT$wtkiT$yF$bo74=IeWdy#i+UJ&hcY4qhg(#skSSf5mle{x$Myyd^RY z4{WSgn%G^o8DRt}p+u%#M7%C@R?BoiMgWEZ=+QaHaxAuD$2-uwcnzQ$8-TKp~d^Iv~bO0#>d1d-skU}`7{=hmDJkkrp0T&>ac@YUyL}0 zmh3ZkA>!q_7?3%vQTXdq{_0`1=3GrT*0Tv2Ei1FJJ1B(|rkhK3rnE?+-I(Cxx zW!}1}_%~LAVyi1P0y-cY5wdfwT1j4|AG-A=iz~Dx0bZERVsn+h1*)VCT6i^7EDd^k ztXkg@G4NUI{B{Kt~j z;Z$Pf;7<4sKp&XWhUx3#^FeDeu(9R1`;wv|MR%`vI_K=N`I3-zc_@`JX$uOZN0EEz z)kh;g@kt&iJDN?2_He(ECc-XDNTPf+9&Y%~8_0+I&|uCTRvdDIVrV>U(LpW|2#pUD zqdY5O#Km$B`xsqVhnc)|LcLJ^Df0oVJ*yEi;?~xvp}ro!V0oqD6Fa=OmCorJcIc&> zlZ*Hb+9c5FKPrGR{vbLHnIura-qcRZXzc2QP86E=g4!-f->akxEwJWtU8IVlyY>jty=51@!<%>JM)Ax;wGfo zjC*6m+^uEyq?*6LF1y_D`5y|50XyB}Q$0T2I#@!ddxLy~xI6rpqD$wtVBZRc0G>C80)k&AZg2oJbY-WwFY2Mtbi!6^Tb; zm7gzqin2zm4Cn79z}Z+Em!7XwP@l`g?43S zNEI0pECtUZRam5w>)V1jeK;_4you|{@E zbmd52r?@H8sNjC!(Q2to<35ztgMa&xI5-#C63x!m9TUXxO%QyG<=i%@YLjb({ZEUd z6e8P-Jkqt!I37}@lg3wM*ak??hsT#CxaHe9V`rw@)?4*dFkO*CZ=<*sH7dxGF%KVH*znzk^_tt6-oEItdUb;jRoLDF;d^W`CCnv-n3eUh3EPPjxCmP0 zJRGsY?%DZQ5w;5+rP*Gfmc93x6tpT-P1mb}p7}t3@vN7kF@$#)G)_x%%iyNYP7+Nw z+gH)^s&n%U+Lo~}eGEp;ZDJa?R*5cX4GjSo{(5uh_VirdgxhzhSr70hT|@ zI5Z5F)fgw}>tZQHBxg^+^J+BE1-N_prf5SAU@`Gdms=-N4M>U0CsyAYff-t1ieM=n zY-kUrpG1iA*|R=S8z98m@A~{?32!`ZXUoifZA9pCLy|HGLlH^bFOUgw^9oSxKcM*y zp&1#8Gqygxwm>zy$91Bh|G^3+f_*9Pxm>%f`>gghO1+wU+^5v2bluF82RNp&{CysN zUWp=5@e$`EdpkSYCpv(MDQt@lqNC-F8dSy$#hS&wheU0+RHIS<^@RJlerKjNFznPId8uhU)Cd@>u9N~YD(qsn&$G|6q`J=WHkaGoBO0NLh@Ie3xZ_49D;d~@Il zc!->N_e5VCbpAUuTsI}aM zpgXdNgWQH>X#_~hm@T4y&I_>r7C^X5-d`RS_-2i>+>J7R7a1{y3s2IoigIgjhLNe^ zo)YaN-KAV`)(ySO#&cZLqisQvQb`z@j)Z5H<1Ct0uZuH!Gl$_iE-l+~CxisIU3Pe6re3I6if~VzFet0{)ijNcYBf*X?riiKZ7#d!)Xf54 zmRN7Z6MlNbPvRsWmZ7{mbJr6N@finovM->Y0>2pZDEAxAd=pG!I7e3+Sg zxDW=ZmAN#Kj?AI@vn7VuWOyCbU6fH&`V$Q2L8`!K{b}E~bM!7mZ)3U9O1Ej>vUpUi zX03@8lYPKLZo9U3@haMbEF8vvhF#!$WZVJ2GaVo)vbg@ zzZ}%Gx&xeFqK&f^*6R)_zfQ+QaiuOHwc&*1Ff0Ean9!ZfUTo_=?kD(j;<7&Ez@6YQ zmssPW0oWETA}X)zT%dwgMA>k>P7Wpa74_(*-aWK|LrUgVr;-Z;^x^xx%Afuj)!F{;^d0C5mPCu#_V?4`Z$N{&<3#ieHdHvx!?VjCTok5;w5MdX zkm4{xCH=KLl06o;kyt`~S9Nuh6`fnYqsk?M-K?XH_M-_?kVWZ@-Y{UNAAo?&LL;TG ze;P8ra=6mE=&^~EeebP>vpeZtS&SNaQ;2N|z4stw^KsXNR+37^qQ_PHdpy`;)DFTD zjDYed2&wuRP%&+dkt8daIcBxEexcfOBErJhc0MC7urlyw)x5*<^(^)ETx?uqOWGm2 zbBm}QA=6_wq$CGe&)?J%epqp{(d2t{bB#fFV7cX!^2}9ng|D}ZAvji*WaEekJoX2H z8>yFDtosnob9bQkDu2R}l32n8#v9oTAm9Iuy(63+qSG<#M}`8Y;Sh96l5r!j*Y2w# z!<5k#ubuy-uKJQZ$lpBU{ApLsxHzl=A6gI`7aajAiXQM=1&BVMW|3Zg3MX#foZXNS zOFZ$;y_r@*mDYX#eSp53`p1+(XtGnSZ@89BSg@QqjG&0MI#Sl6Qn4%R9f&6dtT@2A zhrE1?mW6ZBBXZbcX=vp$Mth61R1@BA8RTFe$$Fv}I#UNmpwVN(?e=y6 zk`y{K!i?dr`=uxtLxGTm(aLo^J(%TK#itdlR^j!Yb*iHP2epGIH09fA;KbdC;yv@?s2(0qxm>bal_*6-qba+q;xrsF+Hz z7-00LW(OYzB$I zQ$-j<1^ovhMr$Wt2XulOa}OX~J-a?aE^$=flt(#WBE#WIi)D=JXD_hEWntQCQgJ|- z-sbvQqTgM2@NtgAwXLttsni+6#B^_V6LZ(S1I-6erfja$V?s=Lapb zENE2Q8tAQ}^!RE1qj{ES2*Ye@`f9HZBF|;eQmxNZHb7*)e|Qp<_B1K;m;wv8PR{Kt zAC;_14el5HhRp#I)r{&|;dFk#)=46OyTd`Ko`FjpHK_Mn`ftwQWV6t?L0N=W7SmjW zaoaWxSik9cDP*#;57td?dhUu$atPdZ50=c$sgcz8ko`tEILQgEp-u02o?a`mNkCj( zq;!5&hVTev{;Ze;UT=7vbED9PE0v&pLM|X8U@XxDD>E4O2Q7mpF;BUt1h*c1t8BD_ zoMAx1_%N^xqN`O86E)tQd1*W|ztSOd=p`tH*9nU_>JgL2q+W~e@yNW%b zxl`?;_I*{{eU{U>=H?4d46UDF(S^5K;454?AKqRP1L?oAq*w#HGdfR5?~=y_4-&$U z+2PJdz+{}L@+P4}&jx=h)=a>%ILt+N3r7x4k~*-$+iZtrS_VNzRTCaJUEjz(lpZ8# zTtN8a%z@zsTH6nwSAFDYjuvE6R(0u_ITcI*7rYXUXZq^yz7{Qu$ZP>NH%I}scbHjW zcZonCUuVrVS%()K)GqyeGT4^RBZ)E^RGeSRmitx?WgLV}bf;)7W0}k$*^TTE-;b%toe;^*)Yy7@X$a4GZoXpMYJqro%(NWEG!f}PF*>j2LJD--iBMR@ABAfQ?g3G*U}-MYP5p%>^V^$2Xv#w(kl@E%t@ z*sIE(p+vMFA`(~#ajl}r*}BeU0&0}c=k zDG=WouF!04L2$qB7lDr%vc~}A`XxQaze&Q?dDpnoXBrfN>oW6+^stSlu^;HQUKcGz z;5i*K5dJ$=PPK$wT1hH3DT5Z{;KRyz(PqipdOa2lMtPf6g-g@^Q;m6zdB$Yq#@FM` ztIZ#9%W#kmiPq+@4!|x?9WfVjZWeNvIBkDEuC{O@@n)9XSj4!fpgfPF;=0^@F9i7+ zq2IrA-23h&m<^ImfX~O2im3lN9SnmGMbjS|5J#Uu0U48@4t1aLg(*#G@0|1KsF9RZ znv()Eg6Xfy3jUS zT_&;@84ywHN`xnzPQK>H5o(x>xm*f2Qv%!M_1ieNHXBS-rUFe#U&D~?Blx=2R2;?P z=+^^~4*cQquF5Chl1zlKijd@Oq?x^#w?Qp`D^MFtWe?lO=}qVg2DYTkOc3=&qr_3%J;`jzFshd_NUW zM_ih*wm-&pYrp70OahLO(m55X$8IfOd03^mF#jxhzXM%Q2dY$aXi)}htp7%2{^?zy zD$y*zRM?E3&@|`Y2*wknf*9Ejia(QCMO!h(Kga(xWb`lr1O&03v&deDWk>%|wWp3n zl^uj})`btKOj)foYG~F;$R=-(e)Fr%9Q+|d>S^UV5?aD{8-kGd)nTXf7BT)PA(2Mc zo-k7U?q#GLuzz^gNz^#+W?uz@*Y|Rbr^3t#0Tzr z@HWJI^Cn2WEf@hZ{CkQnzlydS#_CA{VXj6g5f6R^+H=aR!!tOG8&>X7(Akma zC;=x{ecJBObI_~(z_VpE2Abn16k~lv-FSNCNx!ouYQsNfO(4$j2zz@_>P`a8H$>ln zYHv^0&qwFoqRmkyn5_>JdphtD86UR_ZjIo`po?DC>5^43)q@}yKp1~1w)gJ7Q#<{- zEBY+cI+{UWKupf>+R4pwz*-oO4$qJk-xzEGf77{6<~faP{d%YB&4ka+m!oi!exfC@p6 zK23zHSKU<*BF*1FqMd1gprRc1EKzINC=Hofa zg+BA}3iKS%b3H~(7Tmp;*&Wv7DU?8TpM97>=Ov17Rzc|ywfdBXS+d~s*;~c{nO{Xq zM}W-2-Wm3M@UWP8ZlgGkNf0 zBfccJIA96644{ZYdma$C?wRl2}dSrK{?_lMaj-I_fDe}rhh z$P!JLJWL3Nu#n~iCsaKXH3$I8JCaBGsNn57Z1HPX^3T$?oT#uSa+{hlsv%B>! zV#ag8tCu8wK=&)bd1ig{hLzk0b))OTjee_?ggu4VOE1P>GV^9itM!WVsGMAh-+CAO z?7NUD1Fp)lvW}==Il0>$+pfC3>yTbWIjZohxzFh6erHzqwJR`&%A`BO{8NCMc zZSTAw5Te7yfMXcz^9yB958^w~CIAZ*Ec?rWM3qY9(q_cS#FS;@D{nb9Tmz*F$kG04 zdD{rQ%vrIJmGk8Y{*@E!Y*HoTE@Gi(1FPF?Mq`qwgzoAlEulj#2SP!L&TNUK9wu&& z_UmEnFHt^TX&4Vm65S%PIJ-#-v=9KA&t3t1qF70ItkE(D?-J=w|sT~DI4&}Fy2;iOepj(XAYXjCz$tDo+t zsGX3;0H=(N;~n>D*c}HY;~tH+9G#8m94tfpGG{TAbUWu;wxcW+nLp#uj-O5OYIjcC zj4^NsxcrM(ED~V3ueMw?4j|>{K%ZIG6$EB^9|a_=Nvh)R(<&ng#6*fb`rKsip}S0i=3u!5D~)Cotw zIMg(4^%jdgr~w&M)XAwv87&jGB_N#H77yTOI=9s1qO1K@76FVh2 z!OobBhbp8)aL@j+WU3f=&zgnJ3%kn|xWXMo;?)=J_is!uis16wh*NYXud~|PkWXVQ zB5HyV!mlwgnWtD68epJ)f(@~b|LRmemR|U(->K>E$dl*Wn3~?pC)EP<91AqoU+l|+ zJCPF=zYUuN*8?!*VAQIShzj(7WzcIiY*Y3wDkwVb4K31S1(Kr^2!@kd?!F8f!m{Gs>ja4^F%P8Q9Q zqZ)jH6}$Xx;lpZDCT@k{KtyUyEv)fiJzsJ%bwQ?S=;a~dt{#$p##c8ap=Bp247V2kVC=XqT ziW6sff#iN5T1OzHoFgGkHCTA2OksmtNt4-_npObmhi(){T7ySOJJnq{08HiioG_?A z;s*UX7TrbvOjkq}W8MJMkOR{jY}aL@ zM1EHyzm%43^%h5J($__Y@vc`JjbC2ZlXGMWf%abbSn=t$8tuj+QFO36H<$QB?iY4C zfMt!zq%2&*BNF4l?kVtX6Bh7|3(@t(Av7UmTt}emeataiZV)fOwHjxiRTnN*x8+A` zEOsfbUhqdoM|6M^kSXEZrM#~nRet4So?!3Ibt$cKq{CBLQXyyJ6MGWTeYj0ho=RWz z6}3BBmUtJQB<6B}t^Tuq|8H-E^56yDl5PE5LV6{tiWp6&d&Dj^s70PD`s z{VmQ71={yNF_5A`0&5O0AaOsoi8yGw)H{EFA1x9tYy=ll9398PM|a;Ge|5+iql%^C zGxjAbPj!8zXV5u9$#vVzn{L~GI3>*4f^tZKbS&ZR#p^r-jn^{#PNJkXZf4|i@oSeP zMe(vxY{Fe^Kj9TZsnBeQpipIF&?l`8X&3%j1Od};q3mpc8uyYXAcd0eYd-?~!G1KH ziLKB5PdOs+hP)pyZ;}J3Ch_zzWo+)LMj7O=EcD14NhrLGJ64|ks^bQkIqLCDT)RjcHJU5T$h_*^v%>gCt#NQ@^}oN>JbhH zaw^v;I}((Pf*&TpaN!?{1Fhj3>PQGKM|`8>GN*>DGabKDF6pnjk&UaWP~b!dF5C6% zCr_xyoSe>!_3i6|0sd1+?h=Mipa6}5#v`X6Y6R9QyQdvs#?RYZ+a~jHnHdAcYkSmF z1K+$+(#X%p&jOzaPOa2kr=N>ev({Bjt?Bh zJzY1eL*+Jq|M0Ds8UHr%x~7RODH57wuAvq;kzxQhLUcLUG~Z!y&~>EW+s;Jz5yUa*oM-uDbhgYk6i8$@=6(XX#YcwdYqA>^;?#A^uhUiv#OM;_&{I|C(3i$ zJ;f$ve4zzz7CbM`LTxv1Qf8Z`<3%>1M{Wa<89f;aEFwq()xrv>ATAy{JyaxGx8K$h z;ZtI)($TV|h)o}NoEe_0Zq~h50b25@~Jw|7O+Y!}MZVC%OKO%pbrGyWfCY zRliRZcJLM>>LgK7ZlsVFgjAFb2iIW(I8vmM&H{S@q*R>}?#>LpM5Ux~P3I5W&x$4c zaHMgK-ORKW1Xckf3|mhXl5c=!bGt`RAokT~clbnSYYvv3k&E3QA0Qu|SVPrxOG4vb+IPXP7|D zJ7Kp)54NV77#EhY=m<@i<8&|l+(}3B$(Bu49i#XM94Q_QL^_U<)%*E2_Y6^a#Dc7T z`lNBI6Qk?N`Vp&`4ObtYG(9m8br0G>K(5Wx?k^TUx5sYz`G2_s(daux$esB=~MZ$U(*~zmWARUR3 zJ4KPi0=KBgws-;b|NsB}VD^;(5rF=()}+ief_n96_5m>)g}R<(5o(fPc3p2Y=Q(XA zR_kS$xd)~PV)wQn9FR$xqI8yC&8_KpxEBXydbqu1DZl^s_VD18y{Fy@%fN>u<}tqL z!79w6yZuxPU#_u3EQGUvW`kn#;Yl38828=lYQiTD?I#$N#dGBHT1bLm#&fvk2{m67;Ll#u`5&l;yy5ZB6H z(@X<8UM+?rYT1sHoCet!SJ_|Ch%(Hb)3m81opshF8>X59sO>i)WAw8p1)O}W!qpu! zgRpFGpuewjZ`Bj#4=-235R)PwmhoiYS5gbQVOIn%3 zf&-ziwp4!qh0;e~BV?eCj%g8VXf!jdfKF~{Fe=h|z9{VL%&DhX#vu_F`*R&-l>%?B zOw_#k5&aSi-VFVjHJGHO#6+(i?}Td7BrH~~`-|gH>NyOnUZ&wC_%)?XhuqY{cWsycM*Gb#lb^)95CzIxAuf!M z&he%JhZCYLau9;YBy;2lscXC-xjPr<8_#l00eCscBi`^+Z&T#j>w%q~H+BgMXVu)R0+4=hyeW#R0Fx3wZ!n7wZ!KCoW%f5n!LP8MKaK4pro8c3V141+{f z9r!Gd#0|&^2Cab8jlY>l4&& zSa@f~PS|jN{$&S10I!htI+xWEC`8>X-q3dl z9iMqNt~{77;*pqhwu~s|KW$3p^+xQu!P%afe419 zjXjkGxT)crvXk^1@E4JTnJ6(K?OOE5=X8@U9XwmQSNNwKZKTN@J=q8Cc(+eHUJJ-U z!0)iAbnKoB%hUlkLA#K{lH_)S$^4%4EPEgpn%sU*Mt62y-KX_8t34ls){4MPB+bEd zZ88n-UoA6IkAyD+$=YeWNWfIW{Ig>NGiSK4qTTStsE0xtm+9j8WKV}WvxPlKZbnA_);3*h} zDS>G_gaSny94Xb>bYx)7Q=zdM3D_bW>G!>fmDv{we+g}O?r++w;CZPc2dm3%*2z44 zOjrLpBe5FQ>16V$|1ZkexyAi4EtTom!uFNsly*I+>Xj&A; zmMZ8r#;;^Jt-c|!e#1ASyk*I?W`u@yekT3~48>y+L%wAZa82F=2DZw;?o`#jz?JBq z?qa-62vZ_BQwfy@gR=?6oek{8{)zk$Q~mGZ;@LBmte-MfzHs~Dz zB1N9uk5>|NPxp zD5AdJAo+3LUp!7l9S!JG3hW61$laPgK*{~~B9Z0dp1(uk)GVenywvI^e{U2Z$SSd3 zd~{sQ#!H@=#~*WGqk@1w`5RlCE;)!E(J7~LJ}qK|dkMPoFN+jqnY$;Q`F6Bte^-09 z-uO~6K&rvcpWCHFhE7-MBEuFK++@w;mChCC+34=Ewa(O&;-;U_*6(oN|5pqNGNtW3@FAr^ ztm(z9qj)^s{{ybIXr&0J1OsnrhL>)_n=QcCz{i5l&A{)G6Gu_bgS$_*H7?&2n>M-` z39H=-Ri}hq5mQ5Ez*$8@AhOs>UB|fp|8>{?HI~33Ojl8jX0|!ve)Nkvp?_CKF#WPpW`c7c@;e&&z$@AfhK&Aj5U zUa3&;xxPA7*DT_h3`{)qpy5smkiVr}T2WE!P;Rdr=LtE?D|4=viFt^IbF#1_r zD0{Sh0~fEj+IZ<_?=29Mo6CjsTGdChd5JR5^jE`G@%pv@+i~-D$tHMDtYUuUitR4wRgY0H<$kcmBS3 zPB=VnV#oEQ5VwQf-9TlNKVe}JP5{`Q5D-G!C5|K+;jew3F(xCSs43p0pTQaTctaXd z@rHiTMc?OVEoZSmRsn%J2>(>(j(0*QTBfeSNo{24@TP;LVwUu%-dId{qs+vT|L~2Y zRWloRn=hoTEgF*y-&k*7EV6hC!u>aof(^{XQ zSKfYMHSG(H*tC|_W)d_=*o~<@*a}gG@>q?Aw8I*w^cz)9feL{-?{#icf_SnoK2blgC2LZBKn?hpE`@9g>b$i4oWl zF**PLM~SsdHL{2WxO`V`7sq`j%OT}@uvh`*y0%y~KP@*E*C=?2*7~hfpsqtYkLl{a z;L#orlZiIHFTl!UnqLGs#bIK@47FhPXtj{$881&E8MgnycFwxS9Zx&q-pO7rs1a8q z>khFAZpDVbTL=?PGxduiq>*+7{gSTR4;k|{!YE~A7F23hT<&Ff?JV0H;MzfLYUh%^ zUk+nJ*BL-yxqbhVzh4i!V(U^@&iyD%OirQs|7o50%te^oZ7gv33**JrnMeba{? z#$zEqqFd~Y)}z=pY845ysnZ=Hi;N`Z?21%hmw|2#FzuRk&M0x?*8y$~51p%scdb+1 z#jI~8;GR;SszM0}qR{_rhxWo@8+FGhs$n++mjYWM6sQ#Wbflt#QFPp@ie2f)?{UpB z-yp#%Je>s=LshEK$4~A`b&3DC)yDu0XDmd$9W3c-SpTa+cK+h_ucD!RDIxI1%@7|U z&}bSL$*-94)rmvZZmd7gw3Dy@He;iNlm%j}uELMvaQWJ}i_F_6bB*b4t5!31mEGk z^BKhmu)b_9p$Y%%Ghu=S35&;}eG0F>Hd%11584Xq67uqH%*Pz*{2aSPw7_g-T%$IU z^x*WO?Zb-lF&J}gXdCGz6I0&Bv5aO|izx|H9FrxGVBFnomlP{10diST$ab%bphXnd zfn{(AJceV>fLsQ)S-!ar+59x&Hi$3cy-bQKGG4m-GsI#JaBz4%xN$bg1fp4klG>G& z^R?yo6*z%8*5A598INOw(2l9Lhbdpu!TVle(H^q}!x z(Uv8j{{jFd#jKru3mJ*jp9EF^=b?XdK+r3K!9?0erj2i1gP{b2*B9DkYM`Kt4nGxu ziZa2FghJLCVS>H_<8@px9hvoY8yK*XEJGb_7u6bv%^?fy%%#V4cbCu-X4tFbwF;%y z2^kcHS1QqqLZq~r$lj0Em|D^gpt*+5tdZiEeeK3NG@4TRW8zwiZi2@x1etoB%bCph z6z*eC^yw<%GAyTNsT9r4H1r)tAzUaBJ+J+l-qdXxV1tG3b~dM-A8JbcyJJ2hat}F& z;7o9i#C(I@>ab)Eju(ylOzm1w0~gNy=GMa_wze*|AaKx;IP7OKpz#fTcfT*S*VcGwyPV{zaC zWlR74=U;i47u`@HsPk{sfMXPu7-sYJ%`=JIhR7U1J!HJKS+wRor);!*N*2)XZzs~s z3+ZEtfB*o(u+ic4fCCA-1vmm8W8s_6-g!JdH4cz(-MB_Xf+hMMEu6i0sA>^X;zEu4 zfIn8N|LGydP=5M0n1H=gF{FOPe)~D|%Qw*-|5eMcjL(u)`Lh z2464Qn>LtOzzC$>PhxDpzD8B%BPKO9iR1kO`(AeJ;WiF;RpKLi(uN=sIG$TjrBa2! zjf^Cp&;Xeuh9W&tkZdC-Jz`w2vJS}&)cjk)fjf*>|JSp|GG-Xl+n%uakiH0fYLVNM zEmKi6nJsr8?mvdii{e6z*+tMK)iH=;EnzC9mqdvYa2xW0_t4qYKp7-l4~jklv?F?V zJNkeB0hZJfl_vG;Q};KP{OsI>0NZxpBU@^w-QSi?_gKufl@v3yD`6qCtQ-g+r|t1U zT|M5izaUli%t(Awph<|!Yk&I%qfxsp(l~HhBg=oO*BrSI_^p5hNA7o?NtU&Faj%q7 z1^jQ;pfZ#t3winJ@ykuYO;r7s9S)JQOY~AKR!v=*6z~Ge3_2HI4lAtXF-vDeR`rM~ zo<#dBAf*V7kD^1jfN6n2sQT)zI%RTJvm;Q1L1{j>3)|D_Zc6~e^g+fPqhhnP`y&WO zu$+PYGuWW#!$`9T)Q4lntw7GN-5oD^+jS|LgSVI?Y?i{jRO;9oq~0_Cf5#>DbS{%cl0VAN zhI3-_@*1VRM?ILH7&ciQF!yTRG*Xj=s zILT9dC*exl`;sJ`)4gcl$V!$QXX?>oVn<1e`hO$b`=J9-hI$V|uz*ebfrm(8K&o`? zI7>v@xWTW^h+z?INaXO;M$rPA-vdxD^KjyL?`&vqMxstbVx|56?0%kK!sy}w%Q9sL?p;ZXUZ2EOW{tO2Hn^%;jKP(%Mdb~XoNyKICZ40_ z6b3*&I3z=l3gR1gmAbh0PTRso>j1l-M{JzD8H&sVA@PHU{!jY+I%Tw^O?zPEkI65} z{W1rGFoe4mN7bo?Xp&+c2vJpcN?6O2Bcp8yx6+MZ&<1#6F0S@6H2c|nYh7_uGYq{X z0`;tnkB4>2hnaG#G&7$DGkv=_e~I85`W}iq(4Y2VZA{Oqri?3|S!4rT75A7X$RGPx zpi+%bDXx(&>$L-YM7KFIRSN0ZDEnp zYfz#Kdl5G7ZEyX}sq19`4HoJ{Z&_{9@|{DXvqEr)Vr*tROe^!(K#(G6NA=wBa)&J7 zse2Kqn#ZYR@z)D~6ZFgpt*dta)Z#@yzyKENr~uHIJRrnUigoadOQV*e-{p^p$`_qN zt=e3*+U(as7bp5#B?Osb3)p~iKxizGX0!R)=4f_<_Tj8?2WbnMSSc7dXATaI_>zXo zbB~3er>TH3n4%^ZX8DgC4!44hh2~D24d=5b9OzYtihXC*;`xBWU6Kw4M6*$|5ozFk**)9zj^9IyEGs_TK|e)rdF$ErmMUm42cp`eiM z7A)29a%70HO6`+$FQNp4PEB(nZnj$cByJ%R*~Jv!cqx1F#iKDX+Y4Mi@AyERSr)-D z>4WJ)3HWX<7|I^bVCB#Hly!Jz77oo+soxjKOVw+hGinS$FI!cgar5R{HPhpbn_Fh=tsH_Jn%BIdR0* zk?z)W_ERXi!dGApaf=x1zyA*p1ccR$Bc;aWIG2RN({UkN0UHk*1eHWf|KD4{OPf>b zsfs9dwxaO4!xT3RpNl^Irs7)V2mGZI?D9%7fOy7@Vb)pwT6F4AklH3P^Nu6xu%mpy z^99ByI)MDn|MY%nYh)~uy@1xcYX+@%KRVHYDh4VHPQ-73gG0mXWc*49>faTWKcS?+S~YVH98~@OQaQge>@E^!jI)V zp392J)htPc?c_}B-nJqCLAGTN&8}cij<;VMxJ5Dp{8TI9!fXXIIjTeuR%v2U1p80AV?MpYu+qJLx@|~mV4P@BFnocJ6gWt!!Dc#>JXcxazX5VTUCao{j&JV1^L zQ@lNI6y5X*q77*%9gfm5&(4u_*E#5k`LeL9u1NC-z7`*i@VURZNBcdffaZ3AVSK<@ z1&7_TS-mKKKO$Q>P?zxvT1`sR8hz4jSPs&W@;7>o=@>FfVpy+if^zAf5Br(U}(-c{I& z$A1Zr$uH^qV4uidiESsFheH;ZfhH*4UnSp>C3u@!mK&AUnVFoF2?~iU+M4%iOD%j# zK3#muI6go*r4|VMklJ^KuF2~=g(tA?9s^%fQ3^bSFYK57Z(oLa^e30yjA>m)&1(r9 zkk2}DZg&F)?>ABO0wZgH)4_zN_emVyQZU*XA9*lhpvZbrbcoXfK&o7mZlfLYC>wNb zu^0PTj7#sy8_tsmgb!TK(9$|BwN0zSw4LJTwrf*0IoG zN9kLrD-r+w;iFeVuv9n#5w<`4tkO3t|PD z^(4XLY(X-~=`8om*y`3YcELI1^Aidn0C5%sv0u!yH8<$gpJGI0U@jmti~kND7I~k?)kF9U zSA!G1sw>tDL%t~?AvhmZ>P01Lb>Np>lEZ0$2@F*Z4=eX;U#?O0fRlNgDTjE8ZizDa zySA+{$%8c4+_G4cfa1>quLeu^-%1PS{Rq$ZRSl^fiwY5RH3gY$#O-riZ=Zv+O2p%X zW;mlS;dUJ1X~HkIR7i(f{+JCc0=@gVt1x9JvnI0VfBvX_porWNyy`4U=m8^}%0?T` zq8c+@8F*+2zXwKmSj&=a)MLKja)#D4RSwo9H2lu@ir!~#R{)$9(&0t_nVj%RWZGr@ zZp&~!R}E|69p@-&E^NMR0F|B^vGS6)`w!SJND=?}2{Uo7+jz#tb>4pilw}G#l<5hj z!rZomFMh{oXCHAya{Ux z3^*`HRc=LCrtU0H5|aI8{P{oaTukBf`<(+NP<~*iBAGtI|1&=_MIZog&6ta}A`{q| zYrqZ+2m9L`3fpS4s!JCal{VQ^6RR}*$z5mCY|CvA#uQ#ypHddfFy)F+AC?D-EAm|< z+UK^-6ao+b^zHxbdn6R=tFbiyoMDc6H)QJMI_ZCY)s3UYs)$iwJMY*=|6HP81!!V+xv{fc6Zmnh`-f)< zfQS`{9|i(-Aj-#g^P8-`C%rK$?yGUX$MGoI%F^Y1%eSP{j$No>e@cz=^!MOO3zQ?pE1t*wi$xycwStEDpjw`D&7 zZO#FDwUu#)j>%Sd^V?W(>Bi_lups{qR*Oho{=M`u4vv$HxRfwp2yv?wW%pHXl^jLj zbN)l@PDvP|PabSQSKM-{K`+L*SZVwVv%3L$3Cr8izz>OE0(FXYO|~2VdREw2Tl1mb ze6HZo1Sdhw+yMz7pW$$ECANGH6zgdq%p&qiElTu1vM#lM>1#8#xGhzjN=Cl)y1&~y zyREAWi!+NnvZOP8=vJi`%^}ozND`@DB33{j>B`;XYZX}2YppSV?m|X6r~IjndDX>u z{<9&r@Lk}3R^ej*?tJ@ktC6?V2ll`I$}numQdyXzMcKJQVzIrKcd33PaS|T{8r@UE z|LpmSaN}y+@8L{+bb5ZnU$v?q<0QbQNDcU8sh7Q9-+Dm}n(Aab;2gcEC>Ro9C>=H? z$sCCGTB*VJicQFb34)mVlEOco;jASug9Ir>Y90e$Q*yrFDG=!7ie^G%tboKF<$!C# zj}*}LAV~MIaD)H5#q9(}^U3HKYqP2yMFfp&^B0@a zLa27JAnU&*Z#qxLAbRF@hLPR--VJVu5ne8Pbs_%4OR&>beh4XObvPPkAp1ugB(40Z z6cBy4|MSbQ%VLOEe$S_Gyt(aqYm~|nKmIPnHC!VJq3)MzC1+U%HD&s97Ihe)C5$Q{ z?Ql+)2V-~jt57D2Gbk_jbXxj#_Rr@I0+aR$%g_JedR>HX+T%K6{n-}+kw^3jF<$>K zs%@~}`_i^CSOdXozn9#Z!5EziIFUiRLeZcX5X>*~ZN%F^SZ(r{2>S)~%7sZVo7C5l z8oBLHPf!J0({I@M3)Fv6N{4J3YU^~aBCOcgi?QIvY0Oz(bWUosp z0JE|_{{CtRbm z`i0P?z}cPjHJ0L#_fMu*|DI0O+Y~~(_I)9XY>Az(O>&t<2mZ=jLDnM)q3+KwoUJRB zgj-px``^5ya+Yu%t_jl^F1`D)a3spJYcBYK3nE5}Ytz%|N&5umSO518s@vpIQ(3)N zQvI^@Q7x9=^krl*A~G-+5E;yWJ=S)4pU2fh z_zaROHyI=XSf=^pawOn=SE&@0z05+5^cxMP03;mznfjl~IxTXKtOS&Rv9P9 z&E4vy&22-^qXPZ9P6LZP2D~v}=K6xthls-`W*r?($^fV&;3h18(4YrI)xjV>w5(1z zHe-sV%;R~-z(aqMM0Kt9U^K7|a5!SD!IYlNn=}d+o2dE$5xdQXnC~3VqDMEBj5i&< zI$2jJP($mFnDeu#;(-kr)>z;?JNO#lFY?!~~9D$e6UU7}eMH2RjFpGr^ICp3Tm zq9?9VziW)?i}!K^HO^4K*XP;;>YHpg{`9T7GH7@$SMvLm>QmpCMTry}q&eM&SBatTq>b*#$t?ptJZ=l$1FaaRvUpQPFFZePAS{ z1&xK?Fji7LzHaYu_g=}N-p{Q2q~JKSz-z;O{x7Mk=KToI_f-wdI;dKW(9{-XvlF$_ zb#IUkraKdk4VdDsaoLPy4uQfoB0ARlFdA3}xGXVNV9HNsO_~J@&D4DWh~4JHOm~iF z(IcD6MjMXaoh<+u%n`(R&gXzE?2o^!*z|4Dw!~lUVl=Vwu466bh07k(g1THfzwd@H z$%BU7GqZATf3*TZuigpQDD7LdRL1mWgeLvDX5rwyacV>V+Q_2Na9;6^r78(KXcIxC z4DM5;CYMm(h?+i1(Yh-oU%I3W*fpGu(QYOkZF=4=TXVm6?@zRI{85;SmpNk`@TLHx zNxne<00RI332rKx1>xR*|NsB^1>93mn_slnISK^U?*1>fZbe{$kbwn~{NxZ|ak797 z5E%1mWyNys07BLO3S7&hi3&IE|GJ|=m8zh`YBGMwzB0H1sikjAbaigRk#GP1WC(RJ z5)G?}2_X@Y0o*#f2qmo68(019|B6@54^Ue{8g9PA_vya?WJ)K)rze*mL*|U;k8MsS z>_;CoSuds7d$nq8h?pNDGM!ne5WKy`(kcvVZis2M>8PQDp#X6z`8WJRGw%nhSS2%l zWF{~+7IMk~xQN(mK>R8%-Qa^M6?DsXA*P}AA$RXF}T8t{_=sYu*oR>{ChR-VY@*DMnW9H((u{PX}W`Zn8!$ zxr~;EtT#{`-{}jnb!w~U;ZO%9gr@6a$Kk1*@kEg(#$Uwx-3TIVJm-klKZ4a}5+mn0 zf^HRAP^SpEcSUIeP|R7WxpOvRLNRC-Cic)2Gcov;HC4Fm25611S|+5gc9p6OxZC+#PrWLUsx= zm#d9`Nl}_mG2+4%{^{v|N!0nGB&c02Op=SRpA1wT2(hpXR^Faw{nsWjg2D)Fol4V$ zb507MRZ!vIkB&XF`@oyJaF8ST3izD)a^T|M#>)ean8bbhqi8#)l1${ecVxs6OaB05l^7eEIFYGoo$v8Kz}aZa zV{W$*_lNekOJnM!c|W(xHVvBC#Og^}(GV1XY8#Vlm)cD&q?jRZCAb}oyu0muH3ADb z9sm9q-KDM=#>U>S7eU1#?wya#@s!>vJ@)dPH*9Puy%GYIr`Y=vfV17CI?P(rp8qrr zAsJ=zE?-zja4E7DRtaB|ekHCVtnaX@e;Xq{LOZAX*19C#_j~>heY)8xczOJDDfPd_ zL#=7*b+?uQl{fgY>(jFI^c=3Dd`)jRNS~bE6q(G#SW*qn`QVkByQ*{HS$^_50zyAz zPDL3fM~>Hot`On4jhk%|K_?d_7n*-b;_MLyFzp7XFg~__`Ri!38s=QYQp;-EV*2Tw z25t~dM1N};^4qjc$r6GD5pVo90Zf`dEZAv!TvE;C)F!eEWXm%KVYwq-zo39?qp;>U zD41kZm~RZDHOa8EfB*hQefxp!yKNUVi z;X&{t#%l)2vjlq8ri17pTaU1V(3H zRK=&V(M9`)3YUftRJqDisxu*SUJ35o93M0P;w(xKCvg*9Ga|}7kWLTzyz#9|NhaH+ zf7Q1Lb`AR2KvLU}KmYp{izI|Ff6?eb?m+oMqlKhyB zZukGluR~y?4>fCh9-sTP<IVhOvw-;DQk4FF-^{} z$K~5^vXUOR(^Arm(a?hi0ezJ^A|bzP5Zg$73O)c%v-%>-x^DsvVdPpG0mF89kj?FAJ1&=Aoo@Mr=tXv#9HpO}n9H{2Q0#?84>+3v$)UL|;YJF(F=6q*J@bEeu>ufZwmNk3 zC&J{)haM||L#>gq&#{IP4HV_?!B>aWHr%egvW0kAd~=Q4mX=9P1WnD79C z@+W3u>2n9-soIN1fPr>18m{QxPR#T8;zvsRY;8ZC0PEK?7V$S#C* z{BUTib)CBNWxUa|56LR_%lmx~wDGr}p49NJQSY?CXyfrxqjYXT^ubqPY9~pB>L+TB z(*cK?wY`Op|NA1{N5YeiiUd%|IN%?75+~!SRMVrW>N_6Q@}>yV6c=SMKIosjXqo3X zcBenr!NQ~k+`PuN^V-^9s9&RAop`wtrZ34gIg22JSLQ~>R(-NgW?`em;gnYR06w+a z{j$9~qC0!}&Jy~=j26Tu9w(RzbO_4aiSXBB3sVV<)F6Ud+wZ+GUVe`W_Ol-|i0QkrSWY_G|<4pVMp>;MG~ zF6as&lW{zG3l6Ae%Fa=Z1-gEx|DAUA6P`cAQ$&6(f)}C+5}ld)0RPMH{#PweCe*{| z4$cFz!|w%ePyB~PGX0<7t09_O0EU3TaaCkL$5o+n2bL$}q~CEoGm**f%$pyc4m&_u z!GHYKol||tbw8^JoI(Ii87_EPZ%`#LdI0Fj>rd+%r)_}g7-0VgV7gVYomlf29lIjP z5t##LsZ%e$hcbYLT#BWb4zjb3aoyJ>Pyd{J{)OhR)G$+h1QvD80#ys1EH{`UU!XHC zye74gnKWabakPPXqjbuN4Lx$=W_#sbop@&sv#aO#`+kzo|Ns2q|NqLEvsf6T>~<(J z0nE_|_UxcyZ?Ox?cKr$O_>(4H1?CIThY|C_L%8(%oN!sR0fLomKxmVPR6q&GlB_JbhcuW>p;-ipWJf5OPpj$^`sHNrHQ6Hv#h;RQRy;6*{GH3KbH%AY`xiQfiPC35Y8#L+fmy~wg?z)v|ECs z0KfKvASftblN9ORRoZmbqMC=$OAfoCBrC0Mykt6+w~8Fh%b{oL+-PDIbJ#V)-6l88 z8llW4CO!(Eoe=a2!=klSuc~6QNxmo8rZoIa2Aw&rtL|ijRwjRYHt{wMPsd0Bc4<>sCLnEzKSeWFp(_ zZa$pKqYJ;M6#M6CZIv8e$WEol9Z0ra3QxNnLB~R5FidK}dUZ9Sw#xyh3 z^Mo|9P1g>rrdx@$JRS>xfMau&*bTSPFafJwlTWm|gMUVq@JyZGrjFl^1y{0!Xe^(R zVk@uh_heJ2eG-LI(Hm7^A{2kF|50Ca!r+}yGmS&cMjL;(&emwsKQ4)WPHNJ7fbg--X#M>%GJp&*RQGk@rK|fDix|TUvB6Z_tjK?&{ z$m|}Xq+8}66&ttW)aOoOJek*1A{9y;oKEcTb z4vJg>`MM^Ct%qfRme>B)0}0))<_hI60mMp=qm&!eB@Zcx=?G4yrF-;}nPx3v9Vzz4 zod+WW@M=1iaI@~W7nXH5bJw+7_7$R1j_>cV6s^JCekIJccy+Dwt=$$B5dd}RTcn|K z7d5gB8eveFs^-T{KIu1|DFJ`@U_r}ufrfx6E)4mU*(mh3TSET71{a6WWM}r?&CwRj z_>YVXhqLvRvm5w%X=o#o91en@9PVD31aBcB>aY75C-~iaYA5?!4AOY2gP)~frfpsP zD4F}t31Cm!4~JPAP@FI~o|C>$V0UKV3f$Nw`#ZPKOeD6%YnzGHcY-|i(Y@K~(tvZX zfekZ*8-VGzyDM4COz!;8Hs7v1l4cY>fn&|ze9;|OqTbWIIVnWO-9o_jZ^Hb7I*6@G zEDt;>9Jj(eyM@z)D#tUvMH{@UR!3K%914RkYkx~^WnT{g=?%RA?^fnl&6wNBZ*lu@ zO7^FSVa06ZD8tum9$nmgAZg|=SZVGuy}5LI&sZe62TqM@iQDBN8zPDTJ?1%?8*5fb z9BuiVN}=~;a|Z%-H*B(mKu@=h%5w|YM4#BuJij4+Eq*pn{++V9KT)C z3S=2$K#a304Z|e${N@$*nJ|4a1i3}#@8>X-hK=-%Yp`L+CvuUMua~9eQdqgf zwkqxnj;AL!Y}#E`s0twILP>jlgcFW*Mt38RZbyD|En)J2%=BcpCPxeZ07^i$zrVPT zm)4rfHEgkfR9x(LXXPRi@nMtVx0I8@-%c65U~^)}gOR$BlE5#7r>mzrO``)G ztXj!OBwC%=4c{P2(T(-bHJ(3)k9u)O6xE?TKDz8MrZw8L*`jl_=jeZx0_&(7^~4j+ zIb?>}BA~9!!8g#qs^T)W;{Vazn<6wFw4g`#`?wjgaRfK-eb2$dB$xAl$-pyC89$SDnaEIELu@qOHS zPQi4PBe95whG*@5+Ad>gs2X3`-F6Bf*qxaopQvgci`}E@E*LYLJ1y*a|0yp`A(qC$ zHosB8eFbE-tP?)Hm9ff_3e8D_#F5+LU`lpIW~{ta(i5?9;9+SE*XvIF{#<{DgU+19 zawtQZI2piXInulNe~D8Yv+*!c13ASq_jld*WMa-a9l*?8Rvo2X(S6#>K5{-ewEw8X zmc>~mt_o4`N*kdKP?a`IlY)6#p4;7^alC6Q$dRq1bl{!SkTTqKYplf4-NqlY;*LcR zR!<2CT13Tpylx0e45v5Cz}$(`DhMR)#A$I_wkewF%AO!gsUK@awZg~O`!e0OoRcEc z)Aw&uEf~x{$S7rRE$BZ)JRzY%agNun)`)5638TP-uir-J8v=3FNY*Wb_BZr?cjy2A z|IY$nMvu88E@2bS3G-Xl6u`g6;?V0+awzfCa3HP^FMM~#_SWVdWPVtb{4N2*t6@Xh zk7&ZoVrs+7TL>)P<^!lx)>zA0s&6qZ^6KO52X7p(mfwb6FMJtHrPZv;7b`s-E245OR%3}3Gd9ftt}1@W=4W}BAo z$$shVeO?;+X$3V&CsIIY6|ZmKJx{2v3iJja6#twE1^|a`A%s2lVUc@rVE~C+cdHi_ zSv!+cGFG^?uK<5YSDpDh%ADQX?w2~wWB>d>@XRc#|6h8wTg#a^kkab4iSd~nx37@J zydRh!Qf5)*LRh~Zu&+AL^x^y|(5@}$eh2gYsfX#`kim*3f6xq9(fqe35M)XU6jZL2 zH$muUm-KTGc=xQV@tv7=z~v5V`Qk?QO~I6@&yOAo?o;FKU4~S{LD)#R1lRYkG?UXa zc#l&uYxeFS+H=wUCY%)d63_x`pCt~>^WO&QUk-3OaR&B?RHc+;2Hye7mHur})lfTU zXx7tuS@&xf6@yp+G|RRAUI7TuMaPd&r1tceofp}bhGoGy1!093XY^5TlOU~|%B6nx z#G59BThl*aWYA+~YD#n^$l;?Tj6hr3fN;aQy^l(usQ}X1(AAmDYd@k#>j+-kz!sTn ziP_pcg-z4~Slo5sZGZX1K`=w6fA9OfJAluwp><*9@2<6ezld@fVKf~^vUe#XjhGk& zVR}KlJ_XU1&c29a3ti>mTb-TzE_oA$IdHPq`+{5DyTsFNLq}ylg*=Y{ zKBi*vWO|r_~D5#>$&ETaBTe^zYKr;R(bp>H8iFb2>OE6@f6D)R1#BA`35IPr-}ep4fTs7m)K?r0_H$OtR(4rgqpmH_Du6 zHVs8s4<`4y!YlruG;yWG3~!}KvJCV!rLJ)|p&=jfW@s1i`yB$-PYt&RLuJ7%z5-^ zY>WZfht|UC;j3pM3zqATOpMoFz2WR(r{|>br#YC(=0iGD|B^`J!SYBt{{sxdUw8cv z?VTfzz^Fkg(!{mlez)Vx_usiaiKJvyaN+%;i!5j@0_Eel0_&fr>;M2)L+GB?oz35r zA--_d#~5y~{eCUAjG?w{$l(UszDTyV;KKyuhf73uuJkL^lLV?^u3_y38V;Av<#L?* zWTI2IH4|K5oKRL84;(@H$9^EM6FvLk6Igm!@Y?nfe~CcO`zv<7;#?5}Bs{ zY~FI;p~E0%pEC_uRukHj{a8MD8Ta;ox-1g3=CU5-iuWvIr9V0ge!`Ru{$}-T8|gWn zjh4v~O;GUtE$%~Ir{nU6Ps`$r%|@Cf8HIEUFYOTew_KplK3@wTYJ+G5%FzfRZ3mPd z{}K7MLUh?wt$P4gwJ5kgx;s{BYgTc>V8W2mJn z$*>1Y?vN8Pt9n61&$kVt)AKWv^>V+lPAuQ&HrZ@;c0|SooaG)bQh(?!MWs0;=~V!9 z0P;DgTBCIxm660NlMM~Y$P9ol2vXyc5}8MnpCI~!iGPS9TLOve>>g0(Iq3}PspPoC;%g%j9H&u#Q;YGT z$#_i@L(I#se!8>z9p9y$XGkxHF17>Z$$w3h1qZWZbRejMyv`Kkc8Cam&mb00S*nR9DvQ;_ z31a+rIfR9)!0m&twDM>(KMBGzMjG)yj@t!KXce>f7EbxhZHyOU!&<4k%elofldeD< z&lusMR%7tYw#Sw7Uhr%aH~IekhY~o4fg3X7B!fbiJ99E#Yp{yDSA3)}6E z9hsHFK50qmcHjTh5D5fm@#a6z40a zDE%~^g@(CKZ#*G-I_FC79WE=T)YhVf>@wanja!cFim7VwwMn}_bX3)fjiw+kRH`y{ z3LCdTnO%TwJ^nw865}(Z2Vt5A*n=!2{}e3XkzEm+NU?;lDFVJlU}Us2$FhHg=Wh=Z z=K}GhlpQ~JOeIxj0k^6Kg}`(^wGV@{j&y8_RV!1eas=hDojSHHx34D!WUW~Yit+Cq zQHH@3?6Ih!5l{HHiuD%JIj34LSb0$zt=Kt0^CjnzOKJ!gsL6+8%|HIdvmI=KC3oBv z(TgmQjc;`G%HU?`6wT{BU`p`vYncYa`FaPX6o1ZP8u(xeFt39^C|$SsdD_1yQ~HH+ zED4ZBaI~_Bs06B>GbSYSGLMm`5s8+j#bbmT;|U5Idbqwuv-Ps@G&3Q<)v_iq#YC7P9H!NyZvea1>)@n&EY96BTJqywy=cY zeyrtW#BKst4lZc5#K!dq=|`JAXs%srJ7`YBH2xeBZO=9rQ3g-=Jq%_^d6{KWo@LnW5hLI2II*X{)uK0oKXLIPQBWPAQxN^eTIN6$_hxWlbZ zxAi!8ILJs=e6)nvEgXO2f3PH>XYC<0EP5xBogxL-CHQiuFmk5MA=Hh?hY+56=~8Q? zNC(-`PL=rye|cpSe~n?cyqcPiU}R948K7llsWj*&o+F}^f~2ibK;;ViMj9c57_x#u z~~`VHCspa(PJfk@)M_|m_LsE&(DS++>d3IF*l?lhX&w+iI=somB7yN+p-6u!m6 z9K`+Z3YF$fEIM4}Ub{86BloNfo2f5gkRsc4R@pJ!th@ zybOBXuLkxpV&1q+oafC+AFn(kJGfFWRZ61iQccd;QC=xj{$30V%TjGBO!kFH%YG zb6tar^Yi8S75-{K=b|z+c+V>WBRR<=HM1Z)K#el*>B0za3*!gez#-ZT*fL=BDrHvh zRGDd5I^6Y>0e>MT3=j#^1bPZ?Wa7y=G(%VO1>X=tqLaD!_|Mo)4?Jh$DS`Uf# zfQimlr22zTt_yMP=xK@8;LSjHj$@6e;N2*!u($=`sw(bK0df7!0B_#yzED+@D7!N> zTX1h;b6X+14XtA)f!NZ$r>~8sDvEpC?%Vd}K8h+3G5`JkpCAa^nM`nKr}ZEHy)6?N z*vz%MXM}B6@@kkUFa^M_zdPA|by%s6?O@9EYdzbYi4#sB*p z!9N(%Yi7X6R|^^DpSTG5MUs-C1~VCD0B#~C6jj>yU)v>M01>uR*U=@qySE%Uiu@+M zHudR@JGHoeqT9)xHYbQ4OIybai}GTmZJCQk$WNVR#lN%CcwCK(K^DEF2iRcP-Px{F zdH;oNzb6^Eb%0Fo;${5~9JGZR=j&}hlUOn(dsPuHVm+7GB7oSVhr}Gc-6}@Xdu7Ob zH@iU!Di&Lh>=YnMW3L{%&uX^9flrajicFH44w-Ir>&l5u>0S1{ZIr2^o1gnF_ZNF# zxo_fL0VgoA&?|d;vYVA$9ax(GVal4t*XRh}z@G#_rs#j?8~+F79Nph^g2QzqcM2@8#?@Cz1lDYn{jxG(Ij8*`xj%Opy$XR~ ze1~jaVU;z7$Hx0a)4LUR%=n$cOk>JK@OBrL0{~h$&lU>l75QoJ7LU#{YeD-WpYsj+ zGx)qZ9DNVcTSk;AbmI@-GnV-Vb+80W&wh`FZ9DhP?}S;PGU!K(3NKNo$(5z>n^ffl zjjZZ8>0c|^*fk*91pHA}d1pcmot%6)+JWc=9I`6kHAD!#o7*>QKf{QTvbh0FlOmb^ zlnFzn-b*nl`Ud|L*?N0`G#`ipx%+ID-J?Q(&q$1qN)_l|`<{u7R@ITOt_?c}=RxlP z5+d@77r#AtuK8u{imyxvU|5CQSygWxU$KErI{PcBW)>J*MYFixcKGQ;Ow_yEqO4PzrKP2T6(`OSq-XB zJBH{tCrDQ!wPp4wVEu>&_!mSz5GqRPqO0~#7d^O-2IuI#VK$;Vu=5=YDU!P%xJ$Xm zY(tVoxf>l0p$T0D4*CEF8JYAKDmu-F@=n^YSQK8tPNW%X-7d|IM zF@q~6)~_PS;KCY?Tt}NO6eae5piE%;^Ao+GD$^YhM)ZeJ5IQ+2MGt_LqD20#A)nGRF^Qt99Lcs33V&_|90%Ao) zhNq=}Z|=9-XR&*jtYuB+REsT4uzkm?;g@NTpNub$%*_OJ-W3oWvHbakj7T0v2a8cY z4E0Xrt=h^2?_LneZOH27Q;JBwzP!vfL*U|AX3A*6mAHFIwChSX_%K*^tO4qR$1PmM z;=Ko%8CeTFgdUq{xVwU}{0Op19)ojx%?$3C@!GOM1pZct<@lP>wJHA#jo34~$1f#+ zGWDVahJP-(Ifx={0Nxv zs9UfEsoO!IXc8>K$2U=ukV!4Kv(vmCpW!Mwkj_hBBSS^1M!Jw-*ya3oSps7DBdhB@ zSjg0<^Yh6=jF#o4R(tQhk6`JC05tkPc@=0WvWX1)giey>TRags$VmT3 z|HOYe;TiQRn}*XxucAjxoa!4pcAZi%Te~a8jYa80E+z};ju((K93|Cg7Cw5!W}~4B zsv}Hr#%aT!i+b%lsHRn5V-JYV0;JhRVLVH%Pv)YYlkJM9$vd|6S1W+z_YyE)$SaOIMUMEF>?`fsPq$>YpY7%iM5JTnaC(Ar!VxG~4zZ6w*kweSXNOPOas z5U->E?}-`L_26-xeE5hq0};^Z^~yy3+GqT$fpC_d zIZKMbn26#HQcpFO&FmtaxKf579t0p5W{{XlB=X5yG$<##--5!AyOY8Aw0J@$c?C-2 z43Tz{MsfN402v(G=aHY~wmf=wJ2zwqtbyAVMJUpil(I-QfZ)e*zjBR-F#pqEN-^mT zt8dC8fmdelyG@fFSkrRD<4~*qNm8VvR&~GX1S-s8EaFp}jgl+lGcx|#{Vmf{-^n5k zqk@{|noH{au@0ipb!F)rXffgtI@_50IKUWcL6S{Eg+=1d{-cQ{s0ph~M0mT7r5oig z7f)<>T8W8tn0Dd4^rz{u-c1)+^)1!4@;$7wbwYr@S8|d_7~InouG#W-bP?z_zCEd( zw=gNm;G45cDhSe1^SVh;_Qg)<9wc8G9Hpi;q`}u)I4XE|*m_@OU@#DXNvb*;F#uif zA=V%adM%O7jk@1!|3&op8^=mH)0coTQ=u@ar{3Nb)gay-I6g6+j-X11{~~k$7%0kTYDe+#@}j);OB$5}}pQ zhT=jdl&5V|gW&GHOke+@-^=T40wm>5k>2GGj*l`wiH_CO*ZoPVbuL--w2mQ0T3_>T z*#X(T;03_P<^+Rz^3D0VvC_+Re7kCtk^)#00tB-*YQ1s^Z>B0HUG~_+0Hjxa+q)vAQecNt^y34{E0AN zwLnn(?_#O^h1o$=*KQxWSB7tn8t|)dWweLeB-DRTj$hz#?N@jJ<5>`H-{u$pwfR*| zy)_9nMfW)X4hNn8|BUdP73uPGG2Q068Hl6*%K-Wb9BbJ=PRJboefy}#8hpJ(UT-w< z%$UrW?KvIjFowRNY_J@}kxyCzS_IY)=!owv|DW768MS-7uZCBRTPJwAk`&B!-u7#fxal{eh2=LHtg4>{Q)Ik@U|C*@eRRH`?Nz zsvyct(Dp0sxwHalczAcnpA(mBNo?v$C55`l6oZl#sM zEMY;T(C5q?Y-HK9s)(0;0E1qrCuTE}6+i=1K?@QVXx=yX`?Dz!6N?P!&owsa6t9A~ zt9-FV!}knqfCV%f%bZ@W5Jo3KXg#tW~Is-CwWg z(2;z`dV*p$ zp>+aMGcvZdT7?#&4ZFIK%@B8}RI#aByR3Ay9pS{H61aKBAiR)K0nUODMZcb}i&5Ky z-tWb~0Mj6u1_oF_>Z~a-kY(>2p^Gj>!Z)MZX0fss?#c|@2@G=!AXIrPrk_df0<9+Q zxo`Tu))A&9GY+!8jYY)9ZEkUQG7&z|x%e0;*meBAM1Jkmt2O4#gS1N{y6o?r79~I6 z#^GYEE01j4oXjX)ypQ%Pu|u;=xwzLi4_XU$_@gLL6puM|T?}ush4sGZ+4}Z4T8ggp zlknk=BR)L$76uI*OFz=DE5ZKBMiE$uu!C~=y!zC5PF^Y_;M|@~oM-VO+fR2G&c(X` zNw+F`F)2n5EpkK(;`oND;Y@hRAgZdHdth-O{35jb%!XB=QAtYAo1Y&Xj5#v>@6BGj z_Qa+b-JE#(ol%C#Hl6>A0u_?418_oqqI%h#K~KAf7=NJfD>c%UF=HWCwD&qeI=mM< zL8OUwxwfd!AWLjmV&Z$2HD?J`A*S#rCU>4^;)NW`?Xn`J8^qtQsF3+`|BVr5PLK_Y z<1lZp0$M{VPZmsKP>WUHM&t$=^v>fFW3~Q1luzuhB z1y0sa7ewd4VW?nxI4Bf(Ep2<`Y=?hJS|XUfkppZj39yPMEF>!>r;9)uB=gDUN&b(k zXHy%EHpnRvX@-h*H?U0|a(9BFDf?=rt~3oHNXB`a?tJM66}Eq!E~wbcGy#=^@=MQ4 z{>TkvMWcYT7N3zN43y>ur=Sjhcp6CzrO!J6cve?LTZT?wGsYB- zdqL%-)eorN;he@$bVR6EUKOSI0<*}gu7MWWC>HDfLY$&&+UX@-Ut`XMzcORb>L{A> zz>~b)YLdtkf$N0$3P?$lYoT)&K(+jp#!u*l@;HZ``o7KE9tM*UHupmt-V7{=_qWg; zVFu&&;~6RJNtRi^g#dfv7VPB&2ZeuD1#3#9b#~YG;kB&x6tkM}bcuA_9LjBQ<%Y_VHN0-o1#kfr0!NL!7#)W+<)t-?M zfB&Qa9t+MfrGGoCWcME4kOE11v&qzzvz8f(z@>{x6mEW4>I%Y((&8YC;p-cwo3G(c zMt|d6_!3lxcpd8KV9%k9m{Y?R09t&#`|}BG9*(mu@9wiUPX;7q?$f3a<-R`uU3u0- zMG$-If?xHvYnK8Vm|3QPA=w+cNNmy#l?G39n$4H=A^go`lKNC15vno_VHiT6kQ2ll z!fX#GD!5<~HnkC8>K9QiUYj-^5&@Eyt;ZHXtTM}TFEGUUhAcDHidaz&VjcVJmP^O~ ziodFUK6W~?<;W5#+-Zzv$^dlwY)L9Jw0DMt$(v3c1<%NZ%UY>l`7K!gdhi#Q(gL9E zd<~6RHo^p6tHNzqc}?+)j=5%S?XP@xxmKn1`{h*gbFh+%F_OG_Kil%D*8b~1`+DZl zg9N1dVOnWNXToEaNwRN&Nuy-Ev@g$8PKzCsz=wvxB^>wF&z79SBB%Z8nuN&gzz8$F4I*T$)il* zA$kVS+h(8B3PQMF#$JH+Ter>Zk<>U_&0aamUBU^quHkF#pTNFcRZ6Co#{{;~znRqs zNh$q1OfiTsese>X%2=S0{R|Y%1S_YCTQX)Pne;S+|NEj7is2V|$M&=zh-fzqP|S^s zE&&u(2Ab`vgB<{#QY&6@z9k_iW~qy44pzIPG-M;4qTu<|H(b9d@$LP!%;2-2t5{>e z;wJZ+Xu4o$cMsN{Fa`rXG$HMA=#bKSe{0%BIY6lfAJZoykP#uJWbQK|rZk=Z$a@mj zt}h;SS-NUj`8Q2J%EbA;59Pd8Lao%qVJY6cOhMJC`AYs+Nins$CLVfendbx7p#z-L zn)fDlh82>zpGQ0b<2O~c74kcm!0?}djT(~7ez zAR?)-g6aU1KP~mG*RpO;2J|)PvABv7Wiz?bcD$i7yqNyaP5pV*hlRO_aS#y`2W_Px z5vV%Q25K+Umx}XSUo8!otG%Gdm!3tV+4Mf8jgqf*BNhVzZFy(+ORy!b>EbR$6!e6TCs|psfgjh9^+3KP#`B_R4Dh5a^aw;lqO|U>yci zifK;yLv|U5o@)T0-2p(07uL}kjeG*Ee7Pi_?@2Z)S zlRI9cMOG`lEnT|;(TbsJ*wI=@XSKL7TYuaW=P}}YkCGTj_^1|*&=(b zLH_`U4`8c6J`dG8pj`9CVw7@sb0FRt z%|>-XA{XcW^KpDv4ajB{FW$7uu4z{`2nF-G+(I!07_{SYil0-;LX?T zzugwD?;BB?84j#0;ROX&(25@EyPPURak_u9qfQ3?5_E6Ixso?9 zV*x@`p+hmF*YZT~%}MM;kJ-rL=-o$p+yw!eqciz@4&ZSc3Jc}<3Bn}{`u8YxQQ|`p ziD{;k1^c>^m5Rpo=DqfO|Mcd{2n&AzZ?BJ=fB*mt&?et+s~t>%moJ99Ve5ULCf*4H zJaYAFr~m9@lxp%nuDZ*1XVvQgi~amk{*fJ@#or~(<8N|wD(tz~x*}M?4Qou?c*{0wpPH*$8A9V~;d&oz(B+b%!HMC^>qevuz6=zbAU4(}4GEEKAG@49)$)}&^dsJy0vYCiL z_Mg**`j9iWR;lK1!q^$^q~t!D7z^3-JF2_#@X4M4+^O~f|L}M^c`OXGiKTu2(w@*g z-$P<_C>1F?fh-y^F8F<{K(9f$bYqy0u5IZ}I`w1_KX4k&7R$D6kcKv{8(&z$MY&Js zDpRa2uy)JI{e58e%2L4Fu5#U^E>~~t9mrTrw5#~jU2Y3jKvKF5lcns2nx2;wcxz4e zT6Vo$atd;DzeE00f;v)=FLoR^jN3nN=SIEu-faWd05=zx`==jHufqPq0>(ALj8;N^ z%U#MOaI}U-o!b~XwKrOH{_UI`C8d@r-hG%=(u{=YE!V79T{I`YX`<5Tjra3lBR}<` zn^$v}?10|T60dGB@lh+krLP*_aqqH4d2d6jKZ4bq_7Jo|ACO~> zX^S6I1A_J7vzixcbzf-32rGTdp{|V$o1T>8+!yyNsfGl0B^{}0O!sXxv3OJ|M_#UP zxt$e)zPkO{pwZ{VMx3^3G-3@$Ln=_`6q6{73t#~fxP0S3&$OpM_M~0R5xW)|KQq%I zG736S@H4^9GGR=G&#L|c2UV3wAJ;iLd+tEiAJzr3Tkc2Owg%e(^)jpOS*0O{^iN*OzWw)5B- z#($C%?PhB$1^G)1K`h5;FaPE#{8Pii@&6m3O;> zffaH)xsU7B?!s6i3R{Q_91!1=Q6z$+-1{YbPO88o4K|}H9$=_QklCq~YgNOk>bDl6 zYZp|&`sCF{ua1+?FhF**rAP)w3&W29@8)CoU;Puar>q0}QgCf1{^sfWorYf@6MHND zkfkCdeDyQxb|vzjx=)iemE5SN>;`E~Se1@vvQH64AR4=c z>2gA3G#0ExR>Ei8-c$=nNfN-_|Ku4ry8Fi4j90ku>yeLp!MWv3-{$fzk$5^ZP-)KzVhAF$BZJ-FcOo;(+19tqU&>? zdUo(R^)5Pad$8c#d-R(y%5zUnizy}fJ;y5ghDHn&+Pe1=K9uq+JH>cP{IZHzxTb|W+Hmr`MQNK2pP$U$31p$;p{8QukMgpBY7<18#-6s$ zqk>;@nSEX)Sh_J)<*8PQEmaFJvPSm?wDIQs&22nk2L!bO_TNA0>`H{Mf=ko|{XHQ% z&1zW=a`+&zEKVBiJ8JCi)M#!9*Iw>+Ov0P`sUEVz5M2?P0YTJIH04f^Hh4*P=iY%o zA0jS)YTMLU=CRxmGn32^N15KOj!kk}Vu7~?<#@sr{xxdp@8u)#r6w&VrEeSquIHU( z8gL}Z_oF1rjo#vRc8@!AbpVz(9e6Dt^9Ri|$R&OMcc*X-@^g=DJiYbSuh*ca9ms1x z+(d6Ot6UVK)TBq%yE9G_jB$y?9J(j>u>v9E&tn*bo)Hl5WIZR>5c}>)#h3rxDq5Gc z{b^$*`JbmE2;|sf-$f7uPM+5=K~!Cj`1Me&O+fb5A(iE};6_tC$|G>|V*eP)=j&pg z`pGG$8XYeGM-{x+VMa9Yd3nHLaL+0!690LxqlP!c{C|myB3%}S4)n#|&322P`$vOR z@EG~oUmX(`NeA!yYN=@6d7RMRV3!gi+AM_n_Tq5}uILCmpASxbsQX+1-hq?Hsz6?9 zfu)Vu)WiT!_A4wBND5j4tZ%RpD2Sx4YsDG@z3nWM*e$Y6ZCp(q_^nD~+HDF|AmMkV zuso8uA$~vWtCv#ACH=7hrm;M&{ZS0IE#AHzvQ%udaQgePvREKbq!#5qtreaMzPCCR zPM|W)Mq*khufmtdoU_G7mr|XUVu>i#Rg2G}U)V$5D*S38!Y09YG31EM4vaZJMz`md z@AZhJzIEdRJfwI3$Ms#t0O%u?8F70Afuu=P^SAS2L!ZNYiOG&p8s z6r!X_=)IWHjO{R!)OLWfp`6cxp`#l-Mls^an@0{buL(G$d$FI!7Nx~-yc#Z%70{~l_z4Lg>>2frOpo}$b?tV;{y+iYYC#@zzWYImWf;K9WK$mn0cU+O(Ib4^w`36;@^;a))ApILZf}aiFLT%!G z5gfIpDTN5R-1F;L9$fVk$Lr6Zgczuo5#M`1Ud=RqL@$+ycIZ73qPu=>6Gy#6@10Im zDvRhAVV~6+q0*LOFfvzZ&6Nb0lk{_{?0Rq0V#e~mDM3a9dV~NlJW5IQ*Y{g>+a#+WJShDoU_^1Cy#+?0>(b=ZtXUD zVtivM8+}GRkqdD6kLSS*;tvOtDHII7tM|FJf$a|qar~6)Oi08QOZfn*&jXvPK}hIsmQ&=GuIPc3K5LK*=tsd27+W5 zIvhE1VS1hYFVB2RsqR{FjU9o2HhdX1g)LNJD*`pRCa~;)D?coEg;<7T!Iuk~A|%o7 zWqui`u(!%5Eu92-+_ba!+1%-_l$;s*&$HtqkE~FD-=ELj8=P4GV1-^cpfPd^&5i}g z+N7FEfOn!`H_2q)6>K{P^2`508@~*JL~X;z!=&%qh)3mZd5%0Sf95^t(GIK&J&(48sv8k zZ=S6^*`CCEU}ARc0x{eL)gIkF3ipf|@7(B&$?_ z>dGy5YB$dobR<=A1#acfdNQvGs1&iLvuZ7o1mLwAoSR2xB;uPyQVmI_$wX4Eyc9?C zg#Qobub9Y|l8%Ey&X;?i|3NACmOELr$5>uIop*hS96^-;Vbfcw&o^0&r)%+W zoN87!0}QV3=aVc%l|tK}zdN(Ij04mtwW%qbkT{1Pk=4GTfHpeiagK>b)mft@FIQ1o z(p;^t=Kn$X9MK)LCNfv4wuZI-Po+8Z=DI~zfMFz4%TL!aL0y~K7-gv!20Yo^nVo!g zSApEC#JwSjU%pHZAwbOZYg3pU9Kf8*AY^5t*n=LWu(a!&0Z(0UA2$FgBo)Cotdl^C z>*J@MVN~_pg3pJT3$UmBWNBtLuyEuR2G|VQnSp*HE%*Pf-I?P;T}UTV@`{R?M{yzH zol5jFIHKI%m_>OCjMHltazm8;vaCQkT{B@QbHMnuKiVXFq3&efDxHJNp#9w)B*8h( zrF1i=rj|$9b@aGrwOQY%wdyhN_%zv8SV=y2BPudStK=U$obDZfueO@M#O|5`c={?& z!{!_RqCHTL>z8;sS7j5BkcwU$26%eIMZwXMIX;1SJ^9nRIi7T{q{XRKz~*gNWEd;& zRDGzBzNuX;bt3nG$ke#aHZcZ7Azn5EV~k_{>)ytFJ@RIaVjO0|fsrXf|NgFSv^9~PT7#+uPXGobeV(q*Dn_sR3J$z zs#h*}-B2}>M6%@qRi2}tHy^9x=q9l8{#!3Jf9eOc;A#xsdrTH5`opQI`t$ZLI!>As zwy9z-Q$KQ(r|u0q@J2@6GpMj2`n&fSh>uE~IFMLxik^}cAsrH?F8T3}$d|qDV<+q4 zmd7t2_hcHYZ>66TT&L`31tn~|nC!O^W9aQmabyqMOw_rRg3|@Pw=Nt<+3}Nrmn@*k zN%mizgS?z|xrZAW{mtuvB*#zjLY}D)`zFtAmW-WWXxfD!VCdnPI*xod-=-V)>I6Ip zT3=K#8lWMP>+fZa&`tC*oJEjL9!FzP~_1lB!6-c{8<$KkilQ#l0LIb3|l zFrGlzV#B~oW)Z2?H8ThS+b(Ux*@z4emY|%_<2K#qpWxgOLvAZC1x&Gy*TfNAcW^Y@ zBjrOm2cY=7mp#D+!^AnKG*=W4UBew`EZK-<81`wAW+~v9%FTf!bNa*|w>tFUlBfPX zbVm}>?*`1X)>f>PDs1>|tpNnIYq?Aa{WUBu>T&?!_CKIwNKr015Xx$*a!Fcq0$WE# zR9Wgi@@d?DS2a5j!|nZ~$B*NU#Q0@WvE-q7s@-7$wMw-(3Up}+HkKt&H@|{~J2;?w z+>jnzKl4c-p$ReBnF>)*K49bT8Djp5BnU;BB_7uTMq* zYrqpZH30VF%hqf1oEWAUeqC1SkrkJL1b=$ACqDc7*m4#qOacul&LmTiu>N;5ca;}` zp#G7`lIgEc4qq-~t5Y7(xa^zdvi^$+FM7%Qk87Cg&!>|aSH9fNR$E>k$zdkMA@nX! zQnFRdF<{{<_pwF|fF!5Mi#Bre`xX`h0M^Vbdw9*}Z6}DbMBJVAK6H@yo08&L`~e2Q znUdBh9jRocJ!ozHEb;mogYa%ggZ?OPKEz*fWmR))g zH-1YP3CteJ4KqvSV}V|RWMz%E)P!`{9@+PH?#-hY-dUR4m?R1Up;k66+nAb?43#j= zb@ay&yx@&QWlP`r)hao<_!6l^w)@4O<`Mwf% zzWD?05e4C3U{^(oF)q=LeB+lZjUc0>7Mf0MSL#-EZC{npn>&De6YAG3{76*siDRBX zFBk!UAE1$l>SzHNU!9XW?_d9+9_*m!td@noJTT9TtCe8*kN^Ryy))7QPLy{Z@N!=D zjNJB=1X8h7l&>xM#Vy}#HSpe{TfBW?0v{R1?R3gXYoT=CmE$k4FYjz{t<~hQnl?3Mtk1ra;GDMwn zg6s27L;+eot$eoFlEI+*k+fU}AA%qYXs4glXqidYv0cch?pBm3W7oOu<||@AJVMev z*Do9o!E^HOEGQ<(B{u)-ujH*1BTJj5b%z6H`cSZZ18I5w@*l+WfoKbooFsp;7|YAk%@i~q-M$U!#oJb93{mn?k$+1N;O3RHiSaiXFbS_^ZKurpLuwT zzIu*Oel=+qycj~$*N99#VU)gYEhM`>LqX=4#KpgcDKJJ_3fhCbo#TJyIx5*gI(*dw z8E!=tw$AYcS}JxNA<-Bhd^!~hb>r6^SYc9oMqUjJviqsv<*l6?NzQFo_}>p0wdaJ5tNV=q>%y8amcSM=k0Dg z^p3#0k>^Yf>dA!TT;CrgwyJwHThNO1@wt8eRsiBxcG>}2keISt}oFrY1tP{n@l^0#`uga%EUq7yG6_rhCp^^iJ$ zzr(5R$>@pkru;0pQ~RCZhzvN|#WilrE5)nwu{!B#9zh#agTy53<;D?s zn(fobWHS%_zoYs|TMW<2E)}e(gLY&)0c#~Qy>t6#_$_}(PB?o(5?sf|^`^l4n@b3L z17TYhh__CV0JVbRtP z5Z)Ikoc2mqUB27$fhjVHbb$mp7roG-^%=HJ*Rfcc$^xkJPlz5@|8G^ExJSRoKe(hO!- z)G(A$`Vxz3Q79K81!26<**A0yGnu%#li}c=N~tOkkJtAW^FZZR;Q>y%f}}YkWFjCl znR{FfqAf5KL}N}RRwho`5x+~MAzSYQ<=rK2%j~?5<>9oZy-F%#f>V9auK>^@FF6-$ z4YA@)gCki1A9m%F{VH>UPt$LOCA#lT;T-$q{_=}S(LJ4{(Z>l-Ec&XT*1n4D7?uHB z3YExLG?%oV7z8Z(K}J2crLrKkGkX_?pIz6%wi4cKz7<1D(ScX z$1IjS4kAxr^QGI?>J(vKm?%vC2v&Kz!{jh-xSVjn=!36=)*%?GCzYdC3$X{UR5Hzw4 zsO+ujFpBokMxEcD1TOWwtAd$~VKdJo&ps$lp6g!XEB6Z?9DZd_b(kj6W^Ek>jE5M( zB)Y@xeGaJt<2w`EXGEQVmOE!FvL(~MzZElu2v(vwlq&5sF@TujK+n;LodgpHP z90DcriMylctm*+JHk!UhNG-~^yK9ZP8x-v%Sv5W{+6&hY%&@@NwSKxoFUpObq_yM~ zA{}$;%lHatruuZ3vR`K24TuXyI0cbu+QwYmzhAMF>TS67@$sv{X{zHcAf+=6@&Z{o z^NEl-y0Qs#Fn?ns)Vr*8Nw>JGMw>z#L`~c0(jh}JR;O|9&-;Z*R*h7yXOdt63 z{(d6;fgWzfo1RtxT8GiPYd7w-wF?5@neWA@0~M{XhYTfTTu?W;3z+W#;Iyx+1}Gz4s=BkShTt5p_vl zSjim-)>8!D6DbTTDVkrB%)r9C0?-x}0BGqSQn{;`9C!9_L!ZZ1LCZ#;Vk%F^nzg>* z*L_=`>BV-mTjCvT#2x+9abQbE+H3mpBH|l11n5tTA~TjKVjm{F%Yf=I94=c*l+lE! z%bmxN3+`ge*WErWZ$iNTFhJaRwkJEi7Mb9b>p@`0LeSEH0FgkbtQTChBXB+k{bNL6 z+*F)X4^U1&y3ixUo{A)?asSV-(>p^-l$ykv59Tft>D?}}9MY&*<6)r;CQ=GP{&X?}N&#-F4wBRuTREXXH7T|bySc1%V|4E!!Xa=tKrewpaqhj~ zFWEIv9pjkP1AP#TB+C~j3umjB%Z1xGM?b$+*p9=d{4lLcqsV!jB5DSFUX$^aCeg+m zwSy?rc=Er%fa;(^(o3N*MkTC(&2<}M%j56{okg0`vbb2)TT8)I*!V?R|J^nLz<;IX z*nBW~`zV1d1vfkduYdpmXFUb=bgH`E_kh{;)Vtjz_f7v3-NwCgqgUyZ$wZwCed1sh zuB$HE>Vh5s4?=o5J3`SA=cKJl&%0fLRm&;2+vl~lcj>dtFRGb>STx)xPZ#n((hK`m zfNxM*{M<|Y_&b4ZPX;2eycQJgpUgVyH;g17v6Zv$-%7e(^JFQ~o!Of2begWG!DXj>|APLaekB0eU9oz;64*ugGCN2A;J z;k@xp0sAEyo!;}-A>qfbDZhnV=V}JqH1ivs0D)HOCBV9j0a!L2u5xPs%0+uq(T7Ct zMpt!*%KmHju?I0wO4)7Qk;<_sy+2j9)$&({BSUI=PlL&l_vLqBAc zVs^ul^MqtxSkX)krGz6^7jjjST1cnGC!5~#Meem2&4Ygyd;EBcpdIKo4$O6OXi;YM z;9YqfwwzHXn2utp;VdOdFP3(|3U{m0{kQWkCea&ZBE|Z)P7Nia*&V@or-}FvkMu9u z2T5R&Jz1j$g{?mA6Zybv5hctg3G>hK76>|6-LQXSn*xjkHF}=o$_4K z;-rgN07^cOWo^eHG6~?JJnkJj4BRL(Prnjl`=r^5jXjoA^?<&Z*wc$)&A;6V?^ZY^ zEd6^pjdQ>-iJg^LOI+schmH-X1Y8E%USpIB5-#wcR-fCV{CEhA$KU+M2DCTkd0g6C zroBRN5g;7-ZFtk^k_=*ZQ_r|S$_uiQM0J`Tz@)n>x?ZmY5qar=1Suv_9=zb^r$ z4Wz3|fdw*^zrWu90Nat94Rj6%m1gF-tOdK|To&)w=ReuOdQ3dHi=2)>?^9y2p6rLp zp7RGgln5ymZtZWBq1ZQZFvQf7yWj-JwzpWv?8J120>=d0XlSG}jMyaCe5mn^8smTtvi=8c5u~ zrja0>m%M7t54j7F#83!N`qzz4jArYd(XWu$>uyK2lU#mUO%N7AF+WuV1r!}TIy}T; zg%H)ho>DgZb)q4e9n1z;(?yI7Z-ISo#c56d6~F(J6T-6h|Bre$C!br#_(Gec%o9Sx z2=dwe+b&nt>=~4b#cZzr{9<()o1Z^DsKk%3P*woS z_23~%;$3QgH50i11NR3z2%;vdnkEiQYms7K{01s3VLVG1dIh#FRcaZC4SL*SAMB6< z6~hQe%-f@fQW-v7l4|+>HkR1n)VS0|5Yt;=&vUCW7U{__r*T0xO};I!>8n05 z<|dfF$hz~GU|ReLk!3t!V^5DTlT>ad=!t!jqqKOWBNR!xFt)ZZs*dWV;Ur*l;Jq9< zXKf$ih!6+fGgR@Jv?8T$1?0M>pXj-9ssQQ_&Hb&gW!}^>UMjF4WN={nrVIOF&J>OZ z7l0^8I)V5WtR{s!x0f=iHZV55%d`O#0g}=n!_`>l7V_{MV-b>mGtdB1eQS%?&jB`> zws^Oa9Q6yHFun1*9{4Y6xdBruN*KDY4rM{NFVC8xgA-=m1}HPP895xLRVZ6RyQ*t` zZClZzIBDKhrab0EsD);U(Hjo#sWe0~Q(*8%wOZ5yQ_>k@i4(e>!KiY`_%UByTDg?O zCotiJ?C{KM#KaE06q1>%u>c`-3ldKiWqS7K2agb#GYHg7OQ0Wfzrku2u4$t6VHii+ zSzXsQ{+&8?ctemHNg(}%>{7dD$=T3G%eN$N!#i$ZQ;=kInVvzGRJ5{Rb1Dd~2ImvO zxagp_X%@FcCe+GD(OD>|FS4*CB)S9=RdXU_Lg0M{sk)pN$mYh~Ug6KlDY4{C({s7! z^l8JCZ7-$JR4W=+yd#UDXLf%2TIulJPk6&iOs|KB)r z_~zhoeIlTRSJZ}RaTz*4Go&>RfGuA3GZsge|JIt}WS=PICLTjP5ua?59O|TsrXdy7-=JjxPRY`C# zoJ8E}8neB5d2R|3`G8Qg^8sY0E@p?OPa-<;*2lq&+KmlhDtUg(*CX&%MA#$ph`5S3 zs{MP(idr#n(bxF&3q`g>(%|aPlCzu8B$t+iTH@mL&wGFq1>}#R{YCmD`Kzb}@{I~= z2{{frcKyFuLhOiZEyO?kdC~Xge_!B_`Ve(wwKL{VxN|b%9G$vYCSa=fozj}z#IyG5 zGJD6#LpG>p4z1mq%;sg{@T-;vHgTl1^`zT^=Sw9_CckS6>_*q&(c52_D$oP>djz=7 zexb>K_sx32YM7f&yc%84a(9CStk!q>|NfATT9|vO|0d*oLeYDTv4G61Bb|5GOg+pM z5w;L}vwdRMln*#->a?l!#BK?cC6XMimi0F~;qx)Q$e3sGdxy8rDs%NqQ&yVF?HW@n zw<0^)$LKc`=H)?hk=)ORzugmYD3OJTsRWxh3vG zEqef=f{LughE@8rzoq>r}BI_xt5sOPzOwzgc-l zbn!DTg&YKyM6J@#s#S$w{IYr?FK@taT|(RaRou34PC&Ll=XR8Z{N^oRKlIjaiU;j+ z4k-*SA%|q6_@nD0PFZHWec?>po2TLEO+yO00w|&M$70XT9J8RM>Y%8bgyg*YYZJjY zyMe+w+-E?2ao(~%6Q7cd`QENOk7=LZtv(M!r?cTvfrl1y81^~p4wx9I)}l>JZ;We& z>qappJEY#Y6$friy=7-OG~c6e1MX@~Yc-N=S;-p+3A--XwzgLMG{$)}St>C(>q)88 z}A=CfeOLd;+{I+Nd17qn^F{^uXs^2+k+KIE{+J()0pb;F}o zs$YFh*+Z(g*8*%Ve2HF8^b;1>ODO$fo-1RFWApfF7_o|1U9i(rJEJ%3m_n33zf8Lw zp$9+lT!7l77uI8*UltcobE6M2Q#Qut^ATK2RK_SFjOdbi}dueB?&B$p$ya>{%PWy=1fa|O`pTAT=}ku^Yx%$u9U0S{2jsX@{m97 z%^;c2ql!~a4LR57Wl%$xay+;k{$CVnpDm4C<|iNj#RWiB9_;Qt8atPu$lcd%c-h%)^ zKoO2Xw^34kVh2)CcJU#C20?o;nb zZ?k7B`KJ`VfgI;v$){aX1hd>dEUf`+yoMs`4J>LrMgWg1nF#P1+Qay3XBi1~xda13 zq|=_~RJOZ4oLsGV5)C|-S3xbYXdM;`?gBO115mF{8*sv@e>*IrF$W8~DtUu@qY4?g z+x*hT8(bF~rRitLm1K?aDG56@Ng>X5PL(enon9Sc)%V6P&WSrI|7wJf@ys zqsbCXMs=V(iUHE?am&-1?kgcy*X#7%m#-5LSD`^!Pkyl3X%_3GfZq`F&2qiuxWk=a ztx_)R(S_!AXJ0{`(^^Q=^)Epk7d8Fml?QAZrj&Wu^HoF()nID{%|YwU4F_bX(pL{+ zH}OM<;`4^AILsC+g2h$xDV7!!3FI!Guyo_|#46@_ zrMn8EV4@j*deS0?VsR2*U4&u{pv`3x?sT^0HB);`{9M<$Z{7k_qEbP(^hedSsfS3# zG%)9Ob@zrp+C3(jJ#RN;FsxN%%2}+4Y6L8^uRzG(uYNAzGH#TdFhj-5_9ilu&#smUUpOJrXBcyD_P>HS`eMs zMjn`c4pi;+VH7$ZJ2bA#y)-C<&d~6x{nTdIFnwQ0PQbSBUj{<#p9mI3#`a@Lh?{>( z&4A%FzI(T_(G({Mt71+}#U@dI)QPM@h13&bAlcJu^HsJRYnHk4Oh(sw4*jV|%{#6!tbRH9eM(+%Y2#NJY z{0m<}^(^WZ0&Bjc%SnHXp@g!Ir!3Vz$VxU%N7@YRicNxKan1D114b&2(joM(9KB3Q zY@Hm&M@^a_685>J_osBG>bD4I*hbgqE(c2b-7IzXGkCxx{*ea-Ukd3{YbulhUV@(I zTf!cbE@sx8Pk?)|{wQC+= zn!e48^gU%%_wOkSZlRfF8>P1?*a)e$F%nf_x=pU15{N!!Xk3)vvbqWA(F6%c-$$8BMclL-Xg{b5B$Oxq_9q?3fIWtT zsOxD|v*+(-VI6R6R0>gE2H;=1DyFH0_tBvzbQ5Hj$bR@U^%4z4{KY8)MN}D`pxsOm zO(L(80c@x_|tV#~UQHWXi=I~+$)YXGt!SB0%2sK2q zLjQ&sB{nodftc7`I4Q9Z)&L#Gl}17u|96U5L(;j*uWasrVu5i|w(wXmbb0y$a7H(y zJ+Jz{;c2m7Usj$Lm;qX3X==VoUySsO4Kg&bMG%&XXl|C?v9qcQ-SKctc*&%aTTOMU zDXihV9Zl~n!8rDkN#2(envxc~vtvmSy~MGm*%y}>M&uowLL*{tj?*+yc|(z%MMs#6 z&WP0YK9YT1wnRj=i4hGA)}%i#@1sD->HI03W0o#G3=`y-Z+!zsO*F6z7JS2t<6AO~ zdnoQo4Efj|LI!^L2Wj4U&>VPE>2+#!;v+rxe;knk2OW+yaX%YH-~m-w9xj;ZDiFZ( z6V&3QL;acHjEjAaKQCy!Q)T6l67xnqqeccz z|L%)0#2AxdRazg#+L2Aq_nJOx4LTpIDlBLj{~9-y2JThClk_CKZS@D;-zb}fVpl;? zCQp-sPA&qMqmCJ?;{?w%RNruKMo+KYTeJ>-ZS%=@(LtR;W2FX9RcZ^;8n9A&11=>@ zqcL2Eyn0RO?KflI!R^Io;1gsq&nxct31 zNfrC6B%Ls@XiM!tk0XPA@q8bQ7<#ZN3#^dK|0g~B=h#Zhyxq?%@=H}_25sy@`F_q2 z7FaZuWHG_h^K+~WUIx8>a6bG;azZnooh0rqVuug9UOkE=5k`2;fqt*$(mv;5ESulq zM#`%WyhlLm`)hYxnz<4D1zG&b?cg8Pv5iAnl%?RwC3o1jDk39 zN;!F10B}j5iqOqI9Qi>iG5_{}dA*oXLu6UpDSsDb_$ROH<8h)8@1pDwpBvP6I6l48 z+jvn<=qTM^Q|Daq)Rbl8UI7Q+rs+?+oA}88F_TxcGQZ=$<*Qj+ymCQFk&yjH1Y&^b zT84G7w`UY$CBUqxW+dyK(puIT|8KKhNh8lHK1lp zI6I(bH#g&%(K|_+>Q;4|>xGp2&0c@kz6l6L`V}~WkNy1IO3R|T9;NgRH}5H{sZ9wf zsDL!G*qCtV>VU4vGj1P1qA<|Kd;EcS1&)o0y^B5dO~&+bXT@V{9o&t;Cy^K3jk>~W zF6)WD4Lk9ZJ5sMtB8@bj;2Wk>_DE8~>eI54pit6Gs(@nMo8|O~q2=&0Q==RtAz#fn zhe_d3(^yw+s$^J&mhNsoMp-%YG9e7@K8K}Px2L9v)3HZ90$Bl1v)v*=%`(NzoG(k% zWaM;=W%^ukQ7AL{jczk^Qsix#bO`^v0!$lQ zjRt#zzaj(wB5`T2XvWc@>FSbVZg}c`T3je<6Ar zAD0VFVc&!)bUgIDwJxu>7;Mv2M)lbg2;F%u0+~{ipJPCYN3%}QgA<}89A3;KiGt-R zo8VS~CSlP>G#)ktPg#N@pp!);qOoa*;uN{O9fvW%&{-vciGWg#vy=621}BgrG(vyM z)wJ|Bxb}iQ6!TGw@;8(N#DAZJ6@dphz#Kw{^Dq_5pN+W$BJTOW|NrIPo!;p%PWgHNle3F+-u7W* zGve`AZ7bWG`WdsZjC!^kL;Q}o?d3!vBBX-TuQz7K;ixrkg`bl1Ay(9O;NFrSMZt|d z%|UM{z-acDxc-s6_EiG(Q@Fu5nz?|E-e?Qit;zqQNOwvW=8pNpIj~Q_k8-V+6(mvb z-^Pj}uvYTLS#2#u33P$<^aV`)(EF13kZGl4#rlz>GN|1jm;5m98Pvh+)<#6zZ$w} zE|;NWtF?ym+VpN!ox}K0dc6#{6%6#~^XFCL$o^LvZGDMBa!S4AQmf-NLMLp|lxO~& zy)=JFKiR62O#tZHltfgwB3tOd^1SZk(F5d155g*p(aGl_AT@3;Vh@-5M-}^)mkXrE z;EAZ8m#&PS8QZ7yi9m{W?8#*8h;kh$oP6Iih3#(si=8GQb?Ru{yHi~7@WiiZ<12DO ztyWJ`OxSZx_CnxwKhgD(1FE_V+Vyf+W)1pB{f&#iacK_`q7QP+%voDgBk_c)xc%}# zlD0!#SLN4Ft1nN)CO}Mc%{Bg_%r{o;`mET!&*NhhfmGF;$cPE!I?7J;7B^%M0(znlNOt?EPCfa_n2}?i`U=sZS71 z_WfmV<4H{nOGdjKm#8Eo+(0SOdK$1#OHnt8!MR>Ag+GmEq~Ai!!IU zb&zSmlSzIph#rmJ;&yhAbwzH=$HmRaqJQri;JRg~gY>h}^rFAXU}dt$6Q^3gW0@oC z;b)0~5xmN+K;ZZ8>9+0t2bb?qgc#hx7_5?!t`!`gbpmRwl%l+*%t>`+&6k&SXa2Ry z8M^P=pa>(l&@5yUJ6PO*WPnRn_g&=1nnIqWMe-=cxr{JqK=!>V80SLwkkxkXkVR$o zCaWMgx_}OKd(bt+Ns(o^r^6V`#|UB_8w};B2i)5Su+nR7{^EzIv7sBs*|1*hZVI)= z+(eif$_NdDc3JnWj^Ys-rX3(T=jnb9B<+vtQv*>ScqTW!bXGCSp7Hr&RN5)4AU z)g2n7_KSp1yQ0!F9Ur=T=uSxPWM+G833H2xY&Ve-Xm#LB?5)kLona8nRi_MCkOI4; zo}2w)6c}-Sn2YRJ|3Gl>RfOcTn`#|Aoh6bk?cT+UMD*u0Z6H>Q1tpo1l-GA6v}}&U z@R-b{uzKsdmn25GXRCM3O@6MV) z20267Rsb%di`c*$lTX74Pau!(fqRphmb5{)PmeK6`E`_Jk-mir7oH*I3}d(+}=&ya#}TxtT}USLK(N~acG?rFO3jKn&)41>r5 zJ8-9weSw3&rK_l((SSetYDrL$$(NI9bp@a$jtZ*Od9We}hH5@`#HZXJCIElB5cF}i z5vKqU4gSMvNKXE|NHTFUTy6Dhi=rGD%o49gU_b zKr5FCM!m$LHvVNi(^8wQ&k)q$eA0*_KAxuu*LGx2RBfx4M;v##?O4ykMlh)Nn!Epa zK7l*BgRD`n0%keGqYiLoK)ye;S|_Dd_K1JF5TN=uiA0kR2ivhUbn3JR)71T6=4o+M z#N_2NxXt}9Q?pc=^kTuy@K1M#afrz@hC@6AAL1rIN(7#NaL57W=5t=T zUQ1m*hpPDwvxSLl4s)bGqCcTf)lLdZ*?I>+F#*vU0+hL_cH|kUb1Ma=6a7ooc&Wv= zK_9MJL6Vd6bdB$x=@jN1Y<26;odlB|KgA4OCB*S>L;X(l$vZ_~nS{5ec#a`iM|z9~ zqhwSFcq~VhywLJMLnu)W5k*rAxPj2(sG;%zs`r#Se5O{gAgLM zv>_$TsV-ssBxkiZIN>a>A!p$2GT|W?W9V9Lihg7CRb%hpx`kcda~%t&l4VTf6gW*Q zuH16g^=_;mZkl)>u{De%Sd`DUM<~XMHW1_wR{Ni5ZDWkvcba-*-i?74CEe!P&c}2+q}UzVf?~Rjsk%duQ`#-B`C+UOp7s3Rlrq~LbA_$^&oET z%ROak$yT#EwhE3AOoWqHn;{6NKk-ayBdnLTmU#sd>WKi{NbxtP z|1Q_Hv`=y=@%NKXU zlN`8-R)n)YCVkBCaO(8k;gSxovVwol&G-hd5>7Y|=;me-LO|cAI5tU9?pohFGNn@& z)S~gG+B!t1erFcy&m;|Tqtay+QxXE;=D7F2RN4oSH~+r;p9i+aAg=z{uc(yrCI|B2 zjtRIi6&f_;gY70>hnM+*8_Fy^(*Lcw7>>4WeSp9s#PGK|t!R9F+RYRztz@WKU6{^9WIOdo49CU&iC@>)H{bMsJ)q33mwbVc7exSIaQK4?K4ZY`NVccnGo5o ze{i_~rTpn(+2F=OYEsS=$wNpm?4B8O)UW^J{|ca>r_Tt*uq2sIiImKq#DKwHPmjX^ z?3R5&VX9F#ceD4ZO@b9*%Q6cvTvN@kfp2d9u;NaNoKirt|J68O(nTdS@8U!ET=1tq zvWLVem7j1f5mc(ky|A5M24)3z2Ccn|wm7Ec*1G5kC05MEpArD}p}60VE0~HWs=TF? z$x1jH@wsZj^DmRwH#3jc06K`sJT>x_xp!3j@$FIm!`iutPQ4d3s%#h4v32&fIIMx= z61-VNny#Aa5Cny!*u@TKFwpT>ZmPoRCeOY7$(VVlEdv5t%;8u@=zWNySRZO7H=+pP zzD^<`0-o@Ko{ymkc*(02S(e8+vmm02c0GRa(>um#S6@goNMGeuUM!`lBeC>VJ z{FZ3vrM>y+fMzfji2Rl0h;2FC2}hmA05ZCfa!bt^ydt@*Bb%}Hd`id2uuT(pKwsqBWD?1tPmbmhr!3EAW^8fR@;NdJRcCF`sTUST>pV zgbjU_IZjDD%%$2##q!d6v(w!s#QYAu*r$1(#RhcL&mtV$2GP@I-x35-G-c>xL&BK& z!L@>m{P^qK!Q1|plG$8i|F5n!z&G6t)|x=fNN6Kw{ zsCp`B%{C5EPMJ6xvN?1Vb;0&mVNG4W8jNIQ${hv2K2VLR#owcejplD74K9k;qm(7> zAG5V(QGAAkj<&jsjtS^oo3|)rd~t4j#K8njRZBVn?#rQl#gx?1a!d4YSl&O!ccZjSqPuZ2U+ZvH+Arq;#UGmk=1AxjsNjyaU)OV-`Q za$|I1 z;B>;x)c=$L6F-p&1nbs&%jv;Ar__@eq+Xd_ZP1KpYL~pXs+KFMctyXtH7vr6tbDZeE`z#W4`tpagvDGkG*yMx&9KCbOx~$^9+F-ug?)D}HTYh&mA`wjW^^HORzITpRLpj^e;&u6n ziqZ=04AdM(pX3^c-DyKvQRX|^M?`D00;%;`8Y3wBsQ8cG#wl)t9+`=*e?;choc^Qz z7xKR+T7bdvS__@rLZ*a@2|(0Ig9kaLe*i<3*Odb>_E%H_jS2%Z580gqW z%=r<=JT)K8?{i?a#gTuq9hboWl_1(a?vAq}JznVa4m1DE0|fKlgi9$eSz_vk-g`0D z%wmRMy3WivFW1H(U+oZqL}er+jlfJDOSx!P6J|ERg>8zPb6Juyw2{7^L2kC0%3i_5 zCj;lBx=re$tFn1F)f}d7U7(Erd7^&3{uy&GC0r1o>HSOtzf*dZM8$TSvd+&$yGm_( zg&!nsrIG*3H@3SozFu<(@@ z;#k+`nIr^c4K z7sZ~rN!xoOs9K~|ZuG6BH~lz1@_$6|dGcgn34ocLAq`g;jRpSFV;=0^UDV8cosX+| zYnwz*&*#kqF6hT8>y%KQ3wiT1qG_+-GAD%UE12snN?A?|D4!J+2o;+ZqpB=slrXy? z$YUp-2ba$)3Pmm|jt^1#;CJ9+QP*JnumVozOkkd*KB`d8ii3@_bb1i3hgD4|-Gq|m zw}0@_1h*qAJ?tuED~rWxa21>Mixi2Ev&*=H-JaVLc1MadXw_AY#fe6m!;aZqsUH2m z2FExyRy4tGxH1h;=e}a%r|I3jU?zMoeVr=^X%|tpJgE}n!hr2|<^`-_1y|3ZK4r^? zV%J#a**oVQh~|j z&c97QRYDAWUNVe->n3$EIIJToBxo(GX?=~CZwxz^Zd+m<8rq?IUu^1aD5dj7lvWHbs;ajLYGh^o}g;_bpXlRG~b3VGT~CORWlV%2nP zsWwxxOAq=8OpWDpuYLdOlg^Z)zCpeyj=T>Fx^DxxWxSyPfHjQYl$!MO^(W0m4@B z+dIZDDQlhCDX8lF72D*5Kf0%jL_!n8&2zKKVR4Kp{qERH=1Jw&2@i$t)2?PI{DB~{ zvE8!fT)+Bk20@8`bM9MNj3*pIVu`6f)QblourSa~H|0H#req6JfzA7#9dWT5M;(Lo zro9dpsR)~t=9_%*#qroyS<1d8$dwFkaE!e-J#ze=ftsM~=jE-oi0Q&TZuSFG6sF2+ zs^G_JbzFZLJdDN#Km;lo(Ji^}H3_ISN{+%Qj8)`Pvc^_NZ*;`cm?|5Bta!E`#mky8 zGGHXUSMK6Mhr|E2-zDtU@t&wxR1wgMMpp0>4lSp3iANlpEOo%@+lQ>m(oby6h&Z2Dl0nEwi9dmWRSNY3^Mg!tD7R&N+IsF9IfDedaaY7{#VIK1~TpL7Y_p zO^b#VEfkzY#HN}tuV!g_Wy4M*g61oC&CK7Gc6*E3&k#S3qOcNl)j$4Y zq>Ix3E~&#(EDNyu&BRL6-n$sG?Y$nK?_@7iR`8yQt=TMwnV{`(S=11v(SOM^=kXdk zNOa{tePl2HoV{;7LpbL9988nxRw=F)H@&)h=kHDVp5~g>BeJFLHHY&Eu5ca3NLoXL z`5sv(N0x2WQ~1Cr-f5>W+bnx4M?K`^tSS^P$w9a_B@%0!T`-B@zJ+y^Dv<#j;%F)c zFVnB_6Y*?4N72kaHv@zGoT3RBI=Z_3lT`uUIgLPPjk-};V&uVO4%>xpjX>DIexFYQ zHd|(lJhGg+Ewgk~MnjOP{{pV~Mff8y#05tA&K2lt7Z5}W)~01p>Ikvw#r z{iq4T6SO;vm6SB|+Egpt-D4be0IIC$oN33Sc)QSdWsnr}^OeW%`H_@whs>h#%f-ql zVx=^&F;!R|_SpEYhbFn35DfxBd=$qm)t$eh0o(k|R#lu&&qLBmC@LveDNAh$F3Et= zF28rhLdes(7cUPq>m{z`j~2Mdv;A6rQ$FNgC3)uNB6YM#i59~TKYwz2vS7~sCx0dD zfnM|3cfx{`FX^5&@;^jWmv<=ee?H=CEprwlHSc6~H-Imew5Wq6>!$CM&FE@K0`<~P z{~~r4s52c^VCw(>06EiZ`b`oQlFc_&w`2=8suOvxBJVkSBHU`z{S|Q>Z>cBeDrzv> zac-DtcSKDD58Z6xpdJG&vBvVsEkQ**d#D^9KIuL+BvBGVfDLs1ftj>FU=K_B7cn!Q zp$1%&FiP%x!~;QNv^}-LQpW0qt_e@GOKhoYiy%}v?;LHrinHKaNE4meIrCD<{dn>n z*vgDj<6FuJn;J#Mv)BA>>><1E1JKw7?BK=1NG7FQjA2#E?WDo#ZcL5mNq2P_@o-h#Q|x9L#wAU zoUpEMTY$f>b1>Kpto#A=h&UQQe5*j?V9Iv`&xo8rno0-3G(Hd;@tA1xW^O)dN`38!VA#OhM&i5P$e$Z@1v5WSn~fCzSUeVMUzK z5RD(fY+2F2bn3TK$xLHkzyR6C?E0Gf z3Kq48)cfv^%3AWuDY9T6$$={jyFCQU3cz2Fy4P@1I=CvGN9Cia$rSdW)^cvfUm5b| z1r98K4cn_Cna9=`nFuHZn?Fhr$YPVY+6^lTux%dT5Ah2_Z<{)+{K^R7LjCF(3J1K@ zt2)m=5n%69X$-Gzb{?B(kf~c0Jr&DcyubQjL@ES+^N*Vc$+8AjV! z=K0e|ld(1F;f?s1timANbxLIMd3SMQwzYyE|NQFcMd4A`6EGG__C>>3&N}1{UjVN+ zjs=tm&?)B|kP)%|p%K3(t~Eyd@Vk#x-Dl}38R&a4EI4JzI6*T|RKHPUKJGsoc<=9! zl(e|LLerPWC|}sM|J{D+brXLEjxuRoW^o9onSif4j>OaYJmUp|evNk33m)tGYFJzI zBLqaezjg5!z4XG6>?%lD3ux7olQ7X9PBy8@KrtWWiAH^)}y& zOAaaRAyrHzmRd&lWNEms^rO^0Bxc@9b4NWj8Ee@#V0vpj>v#2>KNqS3>PF%EodOAg z|EI>yuyReF?y=$AC)% zT1VgLtLP^kO7GT%!P%EnE8MfO^w=^?XcCwd$#vi;*^7ZRr{`}Q4P&S3H8~w#YavTd zHOYWrY~b?55OD6N^HJkH=zjkvVIhyKw|N0|8SuQxMYm#(W47`e%fpkbYJQ)I7&eD? z0rm~Nh7d%K@*rg<-Fq!7))0{aMlxcF;Z=(pq*%ur#fB7>=JK-wpX_-XC;M~;H(WmZZ}bV`Xq9|X~?tLj=qC)-<&L;TLFt*Fr?}*KC3Zzl3mPn zNt|~iw{eNY1D0Kgxo!KbMqCe9BbE58R1DiU<|BlwfO_=D!AM}P7(cm|(NMmpfaAcY z^mn|*55DG}hRb7E2~IoM7+}+pny4Fw%h7EdM9wPTt9Tk&f&6YhV=E;HwwR_pK5Ob2)nfx$!c$@r^00<{e=!hL9h}lO``(p*b3UCHVudK5_n|;52JXOYU{8DR5bBxi)ZnjFXMOR zY(ugtx9RW(G^KrcN`6}p4Z!`fjJ4Fv#L#QL!awhBjt7qMpHtKcVGV0&cj6M+?>X+g zn(au-2kWEcV>v! zmsH>EOpC{6s?jIckNk2+ufnSkfGPvSw4MBr)|%b>(V3degyywjD4GF!t=_>!%q4JhB^@*8jg z4rgW}e=i;d7AyIFi|+H?%!(`{h5a=6b&viaA6mfb?JmT)_gZd|6pM|KG9<=a6h%esa^Bye;f^}pqSDTA)+IF;t2J1I0(~ggIJ{#r05 zsDIokj^A_=!4At4B$lYL4G6pB)4H6S*$*Ft%-lS8KajlGG*>(cul(!}JG?+KH)jCs zKm5Wf?evUCdq78$ae~7vq}8!8#}{kvhh@+g$OP$6M^K^Ev4M(hbn!r0{%<)7GhGF* zU&7yS<3$BHz*5S=BgRc#e^R`h9(#!2gzW5vlC?%*Tfg;~fn0j~&Ak|nbq}S2WFvS7 z{@UBi-+aZh%WPhEtQe4o2u&xleM_lf{lZg8UmlYZ z*T%-q8ax##W)R9=4zf4QgCB#YRgP{cxCkzjPuJ(F9xeNp!g2PYn+PpRsP&kRS5E2b zS0_@o-{mM?vWdqsgXuT|-MkAn!~y3@*5v_3XTW}mHNr&}NChJu6o=}|-})Drer8~6 zK(V7VzjJ@y+-V|(O!97_Wr2`gbHrul_wtApB330_+1t6t6_IYEC_sk28 z|6Sljf$c3|WZEMZ*aggHoKg~$tjTsDXnju?g5A(1^sop?>A}7MT6_pk;+TAohZ_2# z(cY;k=0Ic$PY!fb;EjWJ~QEryGX`Iy9b=5;jpNdK#ak8qd}_$YDI1QMeEZq z3g`;)gNzDc83J7K;Zx2a`iErt4tHR0EV7_}8xsGR3fM)Q9k*t2z9K0j;$q2a;z_&i zkj88SAYw7HHHAbMn8*s|($n2?%9nmv5RwjiPs%H@ij!z9Q#MmF+@h0`$a;aYw`iKI z`VWRQ$aJkXnKs3gtq8&Y289S>LX;rfQ_O9< z`09>R7(ol)|Nq*+V)pw`3xJxo{Xw020a#~3-!-ouZEc6mJYuuO7*e`2#ibjhaVp0| zhZhxKtQ>->m;IkjZp9>JIaN5=)h!HxdX5=qpUQ5O`NSxplXqxV?m)gy$0q)aqVd)k z6$p54eb*1=R||;+Op9I*l;V?;3xHEznznf9D1Xk`@<>uoywhZ>na5l_`v+gSMaT3d z7k2IXg$Afx#qZ~RBgWmzSCA9D^p>!n$AydfQI~XQ->>V(3Z83w1IA<(@Y9xVfUf0v z>-)-O&27yxFXeZM!&pza6Vg>-=<(;ecyNFMdbFJ#jbDaK!|0+sC8S$4F=7k zGUFVPE8C|Q_(_{Xo>cLMpElE#uNp&JH!8pbJ{2#x7ocV8o8)o5_#)BC36QwsIqA_P zQ}wJ(gyy1$^%RlttXiqgY8K+B3Oey1FYc4e-hIEDs9~okD~icfu7N&3XEIdH7_|-M zb~XXkx3qYp)a^$fB%>2?WbCIc%f<-ta{XvSfRCR3GcJcFv_Yk|){z&glkqQTWB$@` zXs37;(>YNgS@XCKlz+dk^I@$O=5>1gOk|CVT|}nm z^cRyL2~q2%$5vwc`h(t%V{~p?Q+`S86#@M2{(Mz@71x zbpE9;Anh*L`3W-{=!m8BSI%&KsIcmvoUspWzs}a7Zm0b7yrX`KolfwGVx6LT{Tb!p zD2ruBzTsHd3UvB~bBbQ9!PgU5R%RM&(@Ro3y%a3uG5vB#>>4iy6m^>4%s| z0gxmwyhV-3xvb#Jt!pwF@dzUb(8@&Dn|Mta|4x@Z4wD$YM9|&ZwI+;k zh1+b{?XRUfODMcQZQIY|UXyIV9?=_ID6e{%EA@dHcN=cAtbj!&egO}-+S>*`kHL+J z{_vTWX5gAHR!a*u#GezWNygo$)E~7Je^0h~oCZ+^!3cAJ3KBoL zE~U@3cnTWf9F1**aG^S?=x2@KT>e-&7sGK17_^%!CI+sF(fb|VBYXpoD9YpRckM~= zgWwl%K=z}^0+-HfvLg?aDZV-f_uc*~PEpm9nV%GY zHH=OOzyJqsBw*lG(j_YjQ!N5#7$Yx&))v2!9Dn`7_^z5S|MIU=6Xno>fy)#KxUjUH zEDp6JPgv_6V*y|}qjkq$Rny22Z*BN*dMRZL>b^$W#35xbuMb(@jRb{6fJcZVM|$W# zBe4HjY=|!ndU_4bJNthFI!qYH81z7hq-hFu)2VYkZX#C_zyoH)6CGj^c5Qd5$fo zeb4_S*FhOh$rbwzVaDvK1g*SFXI8*@pXc$^j3Q+25b>VT=fwsL@y`b@2Sc7I%Kzbu zb5#-4-(aU#8y?MLzjSrlgq!b7s!oZT_}f+ipVycWl%dvC#d+lOOT!GeM%rEUiqr>? zrWd4sH6b)4=;yVsaqjHe1ROsRG1mgACsU9>%XIbtVIV(e>T>ZiBQR>z}E4_zz{QMK317*Y^8DMYWg`VSP6@JL((eKb^6f(1-V0ClG~N{sC`ytk>u( zd)CF`?T<}ykvj=W{#0U741rhW`h3pRAHX_|0OD9ouxT~B%kzPzu`_R2&mif7{bLqo zm(^36MIoMjJFvejAFQe<>_iPN%un^&eKYSFtnMYLA7M)U!#5qUy2e2c9hoRozPXIO z<8nndr-EZXDd*$ja=ROk&;ruBQ!kz6EMXyEfC8tieBv8h=87-z}`0S+YYX z;FMphgX7^!pVCMSolM?)07H^!!{r--o1`+ZB_8LzzBNy3AA?|oqyW+*N3>aRabv}M zX~NXD=6Nzp$S2^Tj}+$?G#V$Vpt(Q5*07y9U>+iHIy@7QOt4(7oQH3;;S-8Dux5U7 zCfH5@p7s$WL!%fP3NwAnBd}E$f6nD|g_swMIK#=NqejpF@qo5RZD&@i|NHcX+Ibv* zs%g#&Ouw?8ePlJA9Os1sSoi}$VXHO1YOjkCdlD&#`b_Ko0#N}m~s3d)_J-wcFB4g9J8UAs5s$F3Lqxswd4&n0LU z=}if#DecK?AaRkbrGd*f1&=D=OcYoM>JGKJz5^5gOPM0~)c-eNOc0(ifWS^IpJKV& z`hl;|9~t`R@$DR(nqJ>++G7!`IxWsj*>a z(#7W2&Led*{HNWM?7oI4y1#AeUj0yrmfLRN>o(1uQ9yD>NW$0d5+&<`uw`?fhVBr`Q7(AzEG)S|x&U90E*?M0+F7-)3DGuA?eVK*+qB+NP9 zE-q_kC(8WX_Ajs4DQ@N!(*+M1gAsLC&rRAj)pJ+d8q#>Za@7UAx-&PNiIW=jtVnNM zuFLwrR#Set{|81=lQLDP7Ksj`h~PSF;d^lok7_dl&vF5>doUw)b=%XHcz-3!{^5Fd#r2 z7M#TZmuZr6ikEe?YAm%(byT|@jSyT^^7?~fVID@znfnU>NX|P0y%tN+mhC|!c~iuR z`CM8j)GP%}8){aho?QBz1%{&6>8f9ZV+4%c$|bdL8-{m^3>i5?y$K(XUD@zt4NUNPd3yza})b@?X9xC>=(7Uuv$hc@|#{ltxv(nHn#* z-xJB>$x+KwwB8hWYd;CKavs&qk(f5-15tbe_7n2Udx#+Zr&bjLvre73dB?bAbGfJD zNK|}n*FWjy?n4xo7^zs;+Mx&cgx!QBK80SyLWI>k3KtV z!M>&mfwi1T6Da76fHIacd67fq=4RD6YPD_1$;XQwo&aIxZxtI#`G%doed&nr?rvmmlGEPm*_S>m*t2g~@Z)RvSdg$Gigs zs@GAM6|hpzwkg%0yo|HFuu*lvdLa`bln!$n#8?a3{#%*+K_`#?iPo}g>HiE)AmJMv zLAAD6yj8=8|Nh0=muRw>n-d9P?lJB4@Pt+4!dD9%5o~kdxkn>>)X4|0Xic>Y2kO)s zEOG2@w>#X{6r29nycxB@CaJxg^QVq)bw9(K0&#(?XDene$28jTDIt}>iWAh=F2XSs zZAucC3GNwU;y?i@O)XN!wl$v(AlSgEpSmAX?|u{lqA*|?g1ob#=@13$HZWQ@kc;u+ z1%q`OY}xyRQ>uOs;c7iA$R&A`OwV%{bk;|t_@#XGPDQ>zW3b78-7%Z;2t5lB#$Jdv ze5#N5$5hdFnay!B*lRMDMd+NSxM#AZtr@Tr5;SHE<%qg({Fj<&l~Z#*aWQcsrAwH6 z5B4leI<0I48-(YbmEnLScu(3rIj49!I2`Y3$RBj z>5P}wZkfb7w#c$UrrRKgvbsS(>U9;OJY$g3J8qAfdcE0WD|@@2u?_Qs zXKx-pMF+)X9WYw|T)%&dUt3Hs1^9zP&v7~qn+K44^#MA&5hSbLMJm2Fu$s3<<|9A# zK+dE3Dt^sWnrH_>cA_D*xf0(+{K>3m8Iu44_}r+JUnTF=828=L^%$mfnm{^!uGeWMNPG2ay9Gf3Gn%5Aa3_8u?=GI zjaJjJhHOLcn;~#IpXmC?k=kR*^m@50GY0)5*3%W=xU`3e(Fl!93S684gvi2GTz>f= zNn0deCg}Ck>dVvan;MI1FGz853!YHk9ae0d1wR>?B&Yv}wIYZcyUAVhEMOa{T(z}O zDA*}TlfEr#z5Lhd>hfmGF;$cPE!I_8J;7B^%L`Y_nlNOt?EPCfdW7?|?X&YJYJf7Q zJuC)PHrZCSOGdjKm#5_q+Q3-ClIyHgFrSwrA~|F`BVb}dGBb$RBpw^=Kkg>o3mz^| zKiQs}`SJh6;-ZE-f*eIxQ@_mbR>vl}EkNEU2IY9d6#g}W@n5;|NFRd_{-QzKItWiZ z>mbvCCYQfE5Iq~c#O&=J{)*j~kBgg;VE^7V!FJ3)B=3j4JAuE(XiGkMd+V)VvH*eg z@Uz6gh~8v`>+tmkX!WY(J2+b$VsQs9iT&-#IEhaC7{ny-h=++*T6#@q*u-|QoBti{ zb-r_5Aov6uUSl2i&Zg__o|{tX?Q;YbMcHT2j8pJUsA*<_`b4;l^X?&dt9>PwIE~z_ zMnSo$k0N3Okpyo1llxA|t5f4qxRhgKrFTTIZ&Aje zH>g+qGvF>Nk$^}RT6}$Tsz3Q-p<$2h{tiTPH}eZNQ|5z+Hm_*p&m_U(IM4b`0fBvU zc1vl5;>kdZoi~X9zfRS{&G+~3%opJm5``S^_jbjzT(4ylos5v!HYLU?sR9GRZqQkz z%|F+e7_t9n+zWRspdj(hv4fMNT((1CtCJ>p^9G= zk#9o~X4nz;%_<_NuU&=o+xDvP*T9^>f8KrlIx)Ua9*tLNh3B*1qH!CJdD9cB$~djI zS`P+T7nvz)zNlyFr%e%k-m)E2V+i%;6qZa#Mar=`VO5?*?^tE3J0S$LWZ>apr; z&A=K+vk;EejvznH&A#}(u}?P?Ag7F!ae+FJhu91*IiFQQ))4zU1dgcnYU@_g zSnnODS}_Z?&$R{Cc!Ze0RwBcN&Th4{Y_}dgD*IRzshM6|R%~eb069x~)|LB@mN%gt zCo@YQp`64z3fB@s1fv+ewdzie%3|ad>g^P_mAtYK#kFq*BAx#Roc`grZuP-{V8zgx z=msOo*aF0F5=8s=KCe_$@%oeRzuFzISR02Nafy|L9TD^`^g;g!qu*w{#NkW@>>`FE zeKvwB^^elq=K%0!WTakl1{_h4stUgCSp$Jo6nxBvx$pOPyj2^?^(jcMo_WxLszX#a zOuI6Kxg#;T>hXL&tKM`Vo+Iz0B2L?EWdAC`QW&v;YQ9&Qp3#YL8~^ix>oz?P01G?Ppjs zu#etrNqkPpp2?a4j7V4h*ChrbT;q^o-?F+N2L~MN^;;`}a8%Jfl?bgVyCw5*Wx_Q0 z$JaABZr*4k6nDqh?Cx6OKaJT#kmR#+As}UBF(^|ZYmWb<`2q<PZ|Q_D<^Df+RU#+A z>@3d`Kaw{*d%o(uVGrzM_~@PxSeuC%wwKs)eVF&Lz$_tRVs0R8r6w`@Wci&I;#$`C zfy#L8Z0cKwPMkPfRAXmv$%&?k!sodBLPyj)5H-c+67*y@a+bBAIAe=4u7#W=6!X$L zYivT_P59iL73wvS#wJ-BrmSjK(ZBiM^p^+fl`CeQV3GWdPyYMUD-IE`u9(;x)`#ZG zX5-d*>#ebdMh-D@|A;!`zGBx5GvGKN>_$Y}&%)7tZRk&o<79s9w~H={rHakRy=vAm z4?%omESs46rx2XWe{ua_;j%nR3?_(bDzvKs!^|E|d zS0fP|H91h)0Jp0R^;Y~TKjVnNHArHIR_1C)<3EaQvJt6>m)RwK$OKt3kFf>9)_0j; zP#HT_u%l(soQK(?eI*Pf*zwgmn%b$l%pTKgu%S`t=OSkxv}rMEy_AP-TRBp+Fv7$B zrM3IRudQr|SuN#xl7H8jeqyH-V_m~rEV5^?H@>JCf^dde~mgxD(Tg4*<~^8Mm1m@VR2G z(EhfgGv2Tz1WuMOTFFf~xm)AclvzYOfuPn_SMyTUESum{i zyKLVJR!9$&C=qYTCfv?1+QlMSpp4YFt~p4A`EQ|kYKCF_4TNzeZvDtV{&Sg# z-i1l`(Bc_w@-rxH&w5PVxh!}sAgGXWsC>cGs_BsDz6$2!>ji9WtUViosVnJM=;k$___EK>d`mKzXu zNu_XDXy$R%{(LcWCguUIk-l@Kfo8-C`3&saip&u_Gv<>JFzGLg!D zjXDXSdV{Qxrll|^n7~%s5p76??6Akd=QRI7=*B-`Ga$s4KHWwhC76U(pPMOndu>D; z$jxA10GYY$^rG(?<|GGpR7^F&r6PPWFY>|XVzqNQig`E9q`yBgkJ}DATzZgotWq-E zr8ywlpee1pgk6{uOE%O00C-V(-C;c!H8_k2B!#k%^FvA%ugLts^>pjig8YJ_Dn|E0 z#{E*b3P)_WC;=_e8jOeEE zfpC5OGCLH|%G%s@1^@7H5|$_LA5L7ec|;u$-n4VEFNes8`nbxSlGfpEytv@5{x})A zt-Oc~i0|K(dy62`;I!^}V#UZ6!ZP)t1is(2XjjWa$8-4$tb`@XnL>lt!Lrs_PH0xDl7>qXg%6^MNroCaBf&TO%|oiCLy4sW%$V#qal95ncEk>6 zZ;q>DyTzLo!X3rYUxWOcmz~^LW$eehj+<-Mj~trVx9_#nijY`og5rE_EZZcC47uNb zrjk2vA(3(MQ#!rofn~oE2#*EF9+E4Du z9(PNiYz)dVOIii7spJ1U%uE2HHmw4Uf?-{LWchtyjofp}M6)O@J@3PCLI}b9yvw}( z^oU43ZouROQnKHK$T&>BcqmXE@qhB^aUn_;7z4A|lfuCp47K_DiE}H7j|zTzm_ge= zEhiDs&Z(+Uad$82pYLnh4!x!uf%V;>@Obt(VUiVimRN*0K=&F7U(T%4v)(D0fa}W9T*-dpz~K@PLoo4c2*5Hs zULK>TNOqkMQaerSEt}2vXMl64n6W$pKizrAnR@&6dRpuQqmQC*2yX1~qHyGG z_NdJ`<}EiDFqujM$4fgxDFpQslyvneb**?dedho8BsjbD1%hv8ermR$BgO z<)}rYH`nF1w$GRy)f;6W1JaKlA1p;BZ+&(m={9}^u&>tU-$Ii+4u#>d>ZIubw(`TB z_-3p3mMeTE**N+pZQnhi#+5&BcR`x6w4PvPe3SqG{W-y6b0xao0a3VK2dtvUqIivjT77G2*m57eju-mv|H%nPd!3R_2M zr;JcB0UqP2{{lweEERLfsffQ;^9ZtKvnUVjZ5m*Y*pGBpsUr(bOr@l|5Q5|O@#5JY&oN-tW_7YThvI7oy>Y-2>a%R0(7;h25@ix`>GuEp}Neb_@u`4 zeNGwOF;E_^j(}94wf%TmdG$ECK(@|x3ObH?ll-PqTk}vO$f3R;k7yy`hAfL3L?pEItZlb<;KTMg}st?$H*-ogzD)?+)*zo=ho?2VTu`eE zOzIOxrY-etWPw*YTn)|sI&$MwXkzDeI-)VI8GHIG63A6NYu9Aa^CJ!Nz7Sc=2Zq=l zs~7IZFz)(}LgrPBYMsvl_Th2lxpT57ANae6v%70poq+P|5$|&8&IBs9StB@}Q*_?eTCUqcS@oN$}yqu#K zdCAdmjj<9tCPe)AYp(VOwpcg6-#%e4o{p4L4Hdxs{Hl?gP1 zIruNDLF!Sds{XRR>#E`b3%HV~ZK^^g z?Z|}F?LOy|!JQ)Ub`s(-d;?*ZfU5ksEB`JxX>N;9eAsTbTTW{uIB7GKl190&pOdXN z`A4bCUX;IQxbnZ<_H`gQ8Al|=Xo-MPMnaBVSVH5AG#3y5|MwRE|KE5O@t$7fm^;;4 zS)L!~6gm^^W31Pq;#C?ExfTRnMk^fw%al<>Y{f&yXR*3vyB0v~ z-@-wHzgk%TwpJ~W-K}-P9;gFPe^P9Qi*?=RizG-{!?sqPiOoRn`zZeD7 zQ0wVkUQJ!0kR_ z7XD{7gb$tSkCCzGwBP0u)qUgy9f>*!{x@xkkXn_!gfvL)_wK%TD(k41P&%8l=|YS> zusUgwzyBVD?0$hkf>yz7!%!b#EP`X3H9m{E>V8t5H-{QM9HczpQ9n9f2yE z!wXFPVy!oz5Mk*tsr&>$WwXFeBche9L>$dfX<0Ie!cie0U*&`|Zcc2W;JssdL8jZw zge;O>EfyS~YZUu4xc&7--8$82 zE#Zq<= zQ2~O@P|1M2rdztG=OCGmYbPkmY`Zlq6QNuiYc6Vg6ihIR7xoBi`)aYx(B=Z-Vf|O9 z1Gt1>k>&>P{h=EwfF0U=1w;hLMBXLXPN2wFqbbz+6s+lLvkUSCmyX{*$QzLZLRY;j z9L1S9p2wVQ7&nkgSvJ4>0~u+Kc(D1!o?D>D7hw}gvoIjAN(mtVT~G^Z`L+ciTAe=4Q>e%QX8uYf>%tDA(kY!b#lF8xy2dC(IMApP zsH3jPJkO8zQf9wbFu$OGJRS*}fs0xiN~*vm_$Q)_QF^Af=|f4k_N#dgebzpU0A{e+ z=Xc-3ix5S^sy`xhS+X8_L{AYS=GhuPQAp4{q(^V$D*B&uY86y5v=?}`Li?c=bsi?E zb)_!51p{T9P(>o~6r6gjKm!^>wEwMvXj|kDZ`l9)B=It>D4^%6gwS9ag5-TYVeZsq zLR`p*4+jUx-#eHlwy$M%k@01N*(F**1JA7a-!-E$0RJ3Mr5&ZT~jUMGja25wxtYN9@Oo7 zyfGN5KR|$=EgR*_M9iwujzKPoYUEI-ZuO~pw=nTCt|D`AVOH1qXJXSvt%V&+!99Oe5G)nY%ufk}E> z^nK6kH&eJ-N=t8AP_U4dNl@YbO`5zR^lj)kp(RHQ zVIOjr|EOna{2r6etpFp?;5wJ0986)Z4PUfCTVOwS)png<*4m~I(&n@jr`D*mKMf{r z4F|SUC5p9B>A~CD{I3w7`gyj%RLJY^KhM`J(hrL0-TFjm3)1DP3(4?}&^dz!NB9r0 zyh!b4XKC}=re&`;ZK5gtB$~oH{EPdOL&UxE_gWpRX{~(quSWC!0=x6|p^|x#Rj9(* zTmUsdXC8BI4c0ZWI`l&K@2bRbc$@RpsuFDLU|tb@#hH!({@*R8P0nQpqrl zj`a9orCD8i8NeH=De0W|wrMB^6R;<~B?wA}i7FBFPlk&I_K2X&L(s}j2&82akYnm3)(nH6<4b;l8QacNKE54oUyD~wVJrA}>)!quDMO=$S z(AlYe4q)Iq6C6AE{L~l{5yt`UT}06Zhs0!6kXWE!EF^ZGfB!+i>onm!dh%>?{KT-<m$^Lph2P8VL z@2<>>^$j3;f+8^E?j=Y|+59p(8D)B+k06ZcP1Rg{AcHQ!kf5J)VSm&H$EmFoRbnjX zjER3kESJ_l_{IZaU9GBZwG&W(&!-fQ0!}PC@%EgOhv^gx!5jo2B7Q3F0le1fwil11 zKf9A|DHw!`Id8D(4sH@4*z-D2|2n-!XgTb#n7QWzUK*~kX zt~&Z-5hEOrnJhD9s$DLaPYY+xEe63WQL<*;pG9`4>;MB4i0zZ^@6C#D_lM;?`I=Af z%THV=D&lL2ob?am5mh>lFWQ0k6eiK3X1lb_jkG>srq!eko_1spm@&BK-`&cDU`+8V z6oD?{{nc;6lHOhoq1wYi$YtggcwmjOYQ=%Rh8y*cEoxJsKx(>=d5!MSuZLL|jt!So zS$c)BFsF}}8rMYY4`s@L+RsUND`bu&mHXd>e6_o#v*FIU7=>Ti7^-ZQHcYS$$MMLi zh=?#sb+U}w$HJBZn*J6#Hrg-w&7tH#YTQ}aO~bE^m6bgAG3N(N06IW~@#1ahWBcVe zU2K#Yr;r!6-6k+*(Wb)3kvwnl4v0(^WLJP{ak=Jsa8L0f#Qxg^ktqwav9_EESTMII zo(KFsEmYBT$s| z^&rjLJ*NZWWM*Lu#1M=Fh*VzfHbI_w;uqEq(K^W7eeZ6iH<8PL80(&lj={HI>LfBsf4{qt+-YI2srsh8~!7aES#`up*-K$zFTZR z037RqCI}-tx)$^Q+g;)?S;e^IC+*~TbsGr3{91yiRr?l~Ya0ds|GFFVk^2y$D=|n% znxI}btlgKS)`7uo!b4$C=E4iZCfy6a0{U1;*1uP|$k?o;$U%m*(`pw!O>%tJ509+7 zZYvg?iMk5x$5K%;B|8QR4MuHwv`& zS$!Pi;re(~?v#@b{ppBQj`+W=v94HSYX=^xqJ+wpk8?p9E);PBi8N=cvh|R;jBzhX z>1;Kx$BKP-|M5w~?)tm}`$hTUjamxzg4|Y3C;uTcdlKQg!?W#6;M40X(m~SpW1XKE z{M1jc9^3jXp8x;rX8?zA%JK=uTypz*V1x+DpWA+G*j<%E$-n>gtUIIsMqJ=K zb-qgEh-l`Tb1)2mH?g75*)kTZBh?x1M*c^~#e?#PPp>Gsp@hSsDk12f^=1A1?y0H) zS`hfe+}<)z&4<2yf9j2+%;K3B9D$|LFZQawCmH@a9w8q>Z?1=Fe>m|!Y{M3@7 z#=-N`_@D_k=`w*~bxXY;+E%CMqy}cj@v?KmVp|rd9nr`}XhA*{DaDt@Rd5pj|Np0x zns=N}-y1NH^N&L&Tu4PsKsO+b_k|Q^9#c*;gSG>AFhPD-%u_Tz6LqcSx!7lCXGCz1 z=I7t9|0{OsZ|1Z@R5v#Q^0PN$;}KjrHMnaz;B$K%c)-%#rOuFSC**2u|NpkDhSPp3 zb+KQ_*!YdLy-|c>xs1=ly&sM0EYUi|<$lDh|7R5}N@1fSgc`X{@oACsr;83jpZ%6M zn{7@d`yyL4|L6lt(yB}jMews<|8A_$6o zr_8(+!oyJQGF^SK(t?*zwv|3ZFH-UXMmu@Lgkbil$X|!zS5qLzByAhg{1l4D8}gQZ zkENx4dBjX-mAAn0VcmWg)A@L}zR@JGytx$LOagpZJ{HYdhkWg{<~P+ybnpNMHc>0e zjQ%}TZ9>hvC7Wr|{P_u5lhVVr|Av~x+lH!typ@I@pQx!f3MXB{3?Y%BEK@`YD48xA z&A6~X!@@6}p|ReMukGM(VUZ zxA#y~&)GEjz~jVM9W|0WV4i$oN;xOO-85W8lX(uwbZ{8h-MSFD8l+y2TdI-}0A_eo zYd3BNXnG4SEQiJa|71wc=_ZLq2e*76g8a(i4wn`CmQTxjb)&lCa)Q5SB%GgB=4bP^ zz%pTqY;DE83|HdR*&r&j$d0K9B$@xP|NpV}BLDyY$#rA@EscvQ*YJU8UZ6vveqi|9 z1@qDqwfnO7PD|4{r@Y8J7?kwmBtd*8UF#_IREF}XFOD-S`vN{(Yzv>*nZC;4G7WT8 zSeOJ}x*UcS>KI|{2WbUP8g5=2Ap8Hg?b&Puy07*L(dP&3U+?vp@9)O03dkxsRa;`^ zPZ#Q_XalyDRt@44*S^QTP~udh`+gE82{R0f!wz7*tYc>yyon@`_K?21TqgqTet`}f z!(FU8`|GjJq#}ON)R2#Tg?lTXeZ_XEeHdyiB&ju6aQw7Zo$`ZH^88|?U;XjEGO<0^ zSx6$OHIj@7{@gzfrfH?E@yJH^Os)~X*$f%PRe~oB)m&{DcC|^VM(- zfrE=d*Yxra+F77u0HSXoxr3975A4dEWbiA+Nxo0{HQ0ovgKFQ*eElQ#_Zn)9jV4<> z3>jP_y~Gq33>s6Go749qVr*re2Q>SZrR%1$(tnIN=kyD<)3nVI5tknbCNH=g;) zLiD_}{o7LV`w|!!t_Vo+k%v4WHy0U19#5h&8cdJ!sVYzDo9xY;>8;%My}&o{o7CVv zr^{h!kW6NY>Jdeq0R9Go_g`o=|Hi1n=IX^t3pJnhFUw3*5b`GjYbq;Ob zozWAiXJGP?IA=hsD$3yemGDRm+BGzpPfm=6U`)}N&K#lUp=l2nIVptDw?vET7dGo~ z1l;<&*GJ~yHYq_1p_u2c;@KEAfB*mgC;wCaW9kSc2{ED2X${5Go@5%LACL&NY?J@{ zUJ%ckmZt(7yAg?;4|VpQ&-U#a=AR51AAxJYn4?ppVt;%Ib53iKI0|tgS@HPOoK*d` zLmyuMdQ9^j_XR&I)mxV0M_$&zlMtwMs{jPq_elh+6qVb;V$n_UDn2BmIb&?ZZ4rJ( zitEQ2;Bq-Tw@fSZiHVYY#-Hf+l3E?KHQHHK)u@m9cX70Ci_7baG2f#bZBnb6?in?Y z7u4H7|6fo4{{6|$w@lRV-_iPBn6#N|04?u~kU@zRj%AyXeYsf1 z5T&Ui?aAt#d&U^D?kK;R>jel@8J&4rU1G)E%l^ra$|>n!G~Wjw=n~k_I&1#z#8_Rl z>@_`1ACz<6HAShe(JK2@lZI^ z9xq;=_~Ks&3yiE41b|#_0)5Bg{e62l{%N@azyJNS;VP0cUv|+zG=Olvk)qLp`9Y=; zA>wd7rDd?WV@Ex`?y!&D!P8?~@xhs^wnVFfjl+HM3=8=@;B@p~I51tdTrn=}aH^Au zf4d-DIgZhm&_|^Ib)d6eB0ix9zlxK@luiWqJe`A*Xu*PP+qP}nwr!lYZJ)Mn+qP}n zwr#unoqK2I{lbo@*il)za;o0_1$i^HXNS_CcS8qaXIeqI2;0@@h$PVW*U9sK}W-n>l=pwPjSI$yIVD0hpsQrQDS^pRHL)a`oQT&wHcHocD=sB0Pnjt z@XwY3I^@`wqN*PHoF|`}w0(yygTglCBKK1q1)R!cnP5(ULa)Clvg`a(sL7@ckyjw} zAwo&JI}e!MgTnTPVE(9QlAy#Z9^;CINGmMD%{=|14<4W}+HI<=rQ*}~F?Y4+To;u0 zm>`U-7*UIoR~VP)4Gj6~Jcho{{kfaT`JheZ;@=FVan{=m0JHs?OOBR-XqgV4|}xa!Y?fOO3>v}d;;>jw8l zzq1c7QkKY$?zFWptSUiV|D|W~=yrR5y3x8A%6!FaqvhQ<$aLs1ER6W<@U7tJl&d^r z3mcc|Xa-^hJ4#yDelkE?h*Q}D?D_Onkk%$N(|)eFWh!-b1hOYe{I0X>2whMquk!;L z0^7s1&kk`mka6AN>Z)&1RG1QhAq<-BH26yjUGsDUgzwx;f8p&!4^}`3UeSYpc}nj` zVQphK9wgb7o&rS?l(R>?mSleR?#%XX-n@OHYaN{dp6LrWS|<-dw))483D0$)J~1Vo zdRYbASu?2u_6MkBa*L?hDE31y_cYojQ*L_Y%L>(qyX(^L=LsrRl+wdqos6`ipz;=H zzHzZI9|mw6$XmPbei48bvUq=kQfJ(zzPd-qav{urgRhJam){Odb;4H9niX;*>R49>AKVVa1G*p<)^U8#~eu}E5=Z(^OBO;RCHq^@YXs(&cnRsAkRP?z=7)E_eQ%tiu57 za$(DSem=7oTr_1kPS-FOw14N}UCuuV>tN41iy#hsq>G+g>n}H^h9lZ81aEUWIjdQ= z!Z`R=@5APPt=ue3UhVJw^?||_3x8zX<+$dsc(jQDV5&(Lt}dn2=?M>N79&ZGu~CiP9+VKlS@Thh8AgIe9~ZJz z;=m_+UOFdP8=~u<^|8U0^WKraNL-_tZ4f{uc_r#P8A|^K!3i=a!8n%pDhKE@S14o_ zf@S9;oXZqZ`7*;U)h!4BC@5N+{4Syo_cbE-urea9l65%S6#$V5359h5s1d9H)0)@DE^`p4&c9;$-rmhDSh8WKnjDdCO3ayK)q7E&llIOzJjo z8i3D{j0UoBjBmGd8ojWyn8mLA|q}z`7908skD8O|(HXKb-(P{Os=L8ACVY~~4R;P?;4R~-MI>jfKNhqyP@TiW*PQPASt>`yo*%T$EvAhEc9t?gc8 z(tTf=u2GK>D5Adw{jq;ZSAA-yy{tW(su-}*Y_MvczO){az9)K6U3k@P!KSrHe4{V1 z)IdqJgTsPQr+Lm0^^>1iWHsH;dm9*_9D35fT~zNY*I8rttFO9nZG4%xI}z!hN9wEb_)E^vH}ofZIqD0^tdoB<{kizh6Xy zk5B^33@YKt^wjpEa4xc5a#u>IPPLxgWW23?)7b2NeVGB!DkmJurXTfD-gVFFa zO}8l$uUNYWAN9dmQasi=cezTtFYCJ#U4-6l7K_#rb}*w;r<;12OJ_O=J>b^YraTl; z)UpBN)$q^H&{2uuwRqVVKnbEQVk`iy(Zek#|V&<(RAA^vliYjoy#M?XM*5MhvS#9d4LX##p* zUz^0A7$+gschhdp>YGBseWE4CXVj<`+EMKjt|QQHuizBeIQDV-gRMlO)7%B0DEqA< z30SBQ=oYETT6j*1!rPu19GK$;a;7={FBmx*TFf<_P*0H&i8+{h0Rcq1~g%o+gdRsa49DOG#ZIPowh z{@GLg9#~OnB+JGP&oMpS;IJJoUju8mGlacfFDA0ze{7PaoxzQS936)9m&OWzJDshc zplYY@>4h7;weC(Y(2iz-49YHbj2AqbWQjV&%pS3^oroMGUvP9nAwf==2dovQU8LQQ z@LR*P*yOfo*pz^Y9dI31L=7&f-vy6n#!|}zZr+mctJW-stOWF6Q&q??Z0J|8vCF`L z+qxNG-Z}GQHt_=me<5eouY9mWKyO9$F1R>AXepsjKy2fhz8fDelI{PW~-#LF=NGH zMYJ6x(3OfZy#fVGdhlOz_aR^O;);`5mjSj|20!;xhK8uJ{xZRcbR5nl5-DLtS)tv} zL9bP`Z-B<20BRsoX*cIty`bIepgnM|{2S~v>=@b)MRi!*b;ht@^YN1yVO~v_L{}39*&L)X03e3Gk(y|;@ZYcQH=TU~J;f{%ywb*TRDBgZLTFY7))2OLRy9K7FoRUQbVygOqQCfCoS z4l80OEB~C1sfSyv!wh$^)Jo0;x$6$-C6%QUXRJQ_3jCZ!*Av~05-q$Wm#4k60?lL> zyGz-v)h0KTC}3lLPLe=4N&glGz-;F;Ow`_>Yv;##{%!Cg&Z5D8Sr!k{FM)g|hHy)f zP-s)+c~-mrt2u4rXmLDx2g1}D<6D_F`nXt^-V`V2No!;_V9YoA=OzP)#!rSpHPF(i zAwJc7IFf>Sl@lvS)!wIap$(#=6Hn4$60-%0q_99rKPlm8#Z%(SU|3AEF5BRdmF3@it7YtxsDN9qatGsQrguUG7-3VPGycA#M1-1*~FH z1+V)^n^OGu`(8oWExBq7+{-37<7EKUJY%ihiJ5RSu&aNTt!1H1# zZ!DsgP*%Xx1VGFjsFHDGBwj@vml{-cyR~MI%k>P_&=J6brU-GSuDQYdW+(MF9~kl= zE6gMJK_m*gZZU0l=Am7P771E!LizOF4(S7uZv9tq2tTn8%02~^3uM)MZQ+ZG0TFhG z&g{@e_$Y%-r6_fEW3HS++VgVpV*a_hC(_dTeyq^nzAkio*gwN#wzhAgwv`>bfy=~SUD2fS>jY6ttcHyGDXNwH~XZ^#()lDJ+_#fHI&N-r1LQzvuA z)yogN)=u}t=O1c_Mfh5GIpjbYPA!y22@$J%b9)5rLbXyhp>(OCHOXpf0g#k730TK&C))|`!){5f4CrhCUQ&&J zg?`Xhe{*`LOO}>rFG##kGPTtKqnsd;H}(18(*|CmX{S8D&s;o7KX1Lmx7V zg0C-H8Dhm|s~^RSoW$V6O4sxiy zHY-#ky8u+ugs^EG*U~g=&o^exwAwO&*J^~OeEDKTCwKsi9wGW{<3nMnPK4oCodrXw zw#dsI{d`+jWNbi1sT7vgbji%21SUYNaQA@X44;2(z*~QLdM#XNFiTb**}OpVcUy6V zUlWnRc}i)`hrIms)`UxJlMmnxO6LwBw$y2t`|xNzQ>nY+tM&<7~uisij8vwBin%`lh3s;1WlIh8;3`7Cy1-4LWV=#hhvXe(9>6T_i#;51W zhs^n!0Mx+mmLV*h?t?^)IdVXk;EN438shtx^(nxvfd<#Zx%z`n#^ii}ciByFlY>5- zn~}{QsR=aHeWw}a2y==ktHpuq6u1U*=*{$(RBR?GZBMh3ai+8AUSwCg&6C+PObGFm zo2Riifm)n_By~weEJ{u#Za_M{!f?xb_)Z#KBMj%xiKB<}1Rwrr3a>U@ZjyUz_iK$1 zoiB$JQ6^n)zW6=WJ5hdt(nUft@CjTPJS}}TO$=gLJnmOFI0Y&}4p;*U;FCe`U3sQx ztJ&1V0puSlkKa&sCS7rjfzaGI%2$6%)9E#Wh~)N-*yTTP+U90kNpQ}tC-*U(8EP>u zU@wL5&AgyK7Ogh{J1I*f4L_EmfL58)6MsXUPKX`39YeLUuD*+Y`{|azhwB*or|X`w^e6mooL_cdhc;FN}^w&uo9wq;D4Z0a20BMW~Ja zGd?;*TS#~#S2=%+m6}uH{#b~-0^($zW_d@u66|lwpA?GkZej`qX3j}NI1}(;Z2wDAS@# zOau#UiE+ZO{smyO)jmAH6&sv>y$dDiB9zf&5hi_aX|=)W1+g5_t2p_Pwc2#d7)W79 z*eb8Bs0T-53!lT#YdyOZmr3yV41@V%84&ik`}xqiGFzD_VrTKe!S&E*-qI`{UtM1r z51bp!ifFq@PxJpxJ;c^18(P3ZQ_M_r$^b5rnXfo#2VOoI*HEa%JA`(e0f+B;^M_I0 zoF)K!fX#ZSL*_33*!#F5`?|v#07SlK_Lb?|g&U#(NQ=k9blQ)PwJED1V}lD4wU0B~ z23Xb2mt!yX7=bsLJ0mVez*m^FZXQY%44uu1g~WqxL!GSA<>g;_HJ%n1&U)EcH((~U zZk!>RrCs|6%6nDfB)-kW$2_VF#pCx`Su*pf{15n$Y6gTivb>aIDUI-fDpUy>6xdhF2q+xT7305Xm((;l zdljX}!L!HH7)%+ebI#Oca8DZo_N)|FSJg*q|P3&Zl%e_6Wuats4G zEkkz{2b!X$jQ&3w8Sm2ckwNavWN`W16pktQ- zlrPpT62r*ml000YTgdUt)s9tgtglRQY&!uevjq#3Lc>2%xcH4sJRy@{%2>FwTU~Zj9D0 zltq&|>a(wY^MofjvOTo*wv3A^j1y3v2jBzW9RkzNQT0b$U?pnuUwf)r`(xX15b6rZ zS)GUwPZ4GH($W~%0YM?o-k$d>&LMbt*4#WW>)LQ>ROozD9W=QJFzE~+pXQE!lS-;- zPv!1Gj7T5UQFs+pLKi(D)s~v7#dNc22T`7;0EPa`g43 zj4Vghxgc>MU+zzuR5kt!`LAH!T>Cu3%0v`zy%m%Fpm2B>!dX~&3k#S4PvGLCO$!Eq!y%M&!pQknHTPI_>t0 zrtbeK_5S=r;}21vm$WlM=>Nf$JGyyU)wSy4#ePFUEgFz8<Zx4T%wL= zsQntLg=jxPA&&`w&N0URD!+U8;UPEtQQ2`>yWVEth%j5f=b;uYhbe4;Bfi5+ra-K| z(71}3S1}!R1^4Zd#G5^(kGC)SHec07Lp)|(@&JBDG%WX9`Jky$REuDO9vMR0esb>i(TR7}Jb zNn;f>Mv%~ux}Hv$tmNg**f#S)Y!>gQVj8A+@}KcF5n=8p5X2sg#xfU0QJ4jKfCgqUW} zA;B(9M1pc2(g5y#ML?JplG%uxOuyYxi|%#f8UaU=cyj#y$w5n7`+TeJrWAa2LgER_++!#!=^&hK_Rpw;VnIr*D-!>}Q_N*&G>_k3+;%VVL}v*bC!GV*<$ z&?8Qf+v@cTPU{Rz1<{^|i@XHlT`~BSacJP?*W$R<>zUxTK&enMTlx1nuwPdKEipZp$a|4IA(Onqa(G#G6uH+)WgWCw9>L z6v1wHoqExKd7Q6h(;Voc&ax|xpe*!_n8dsmOpbjnS~2rZw; zsK`oC%bGA<662ll9G4G$#ZR7AjQx|jQ7)o*m*nDsuL0E>*R>mkAYh~1bOFBGqr&BE ziktn+0ne;eqG)@R?oA(7d_H;`4vKz=@D&e=)ARL6f*VXSC9oSO`sc^+*zC&<_J*Hk z63xVd6P3y~kec)pe~#iJ0^ivc{N6#5_QzKA#0yUmu#os;1r;Byotw&rUO2|CAgmm% zY2RWu1hVFDnTjYam)(8IcSLh2q;-wVQd&Z1KkY)nV z{W1T!l@M8rbe${r9t1@;j;jBtL6QIijPuH`nbtUJAJ7QSNtW<{Bo^nTEv#%_{LP!8 z_&q4J_If?d#8Xt9Kj_t}mkjV?B)vxMguPL&7=C=9Dn;g(BBdSvfxianMb5;m*Jbb3 z@NzR0mFwH)qnX=@gKc%a6h0O&+PtF&){{MhlnD7BP+;GWE9>-4Reg0|YeNNf+I%ll zhc*QbV>tN*QNfpt5dM+r0>e~#1dVy$T+X<0quj?U&2s&A_SzV1Hfv*VXCECQ!s3=6 zzlSz%iU)x_t##txRvO`Adbr+0GE9SB#m236;F3cZ@?wHlfL5C2BW_I1!lX)xVpghS zcmGg1QdrbrwgTPH%Mbeo57H$YNrHazA{!7VCT7}-;A>_Y;~5LR0*qV?l~sE*#-hvf zm6s|K+s~kn+;fAa!q6XITqLm`L3KS(*0|HKXD0bX1fYV71$57p!G8jcJt#*6l2P)^ zU<3|fYnmzNYIC&xg2SKnuaCtfXC{p9(fMLKrvxt)5uoKrv=*~O5U%ovf<>)a(3f59 zp+zmA=W?|@{-~01rEi!0#AT(&<_&v?4{cGFQ8KR6$QaXJb}A3{qNBda0ox>J`cC}e zExJn(Tb}D8S1z2uOGGA0&MhN(0P#(C) z{WH3{|*(V7}Os zUp}!LtOKwPe_RkHc4v@uEimhIs$MOdg)gby2396TI!oBFr-Vk`P|p^vnbW2SRW%&) zfcLBJU(BYf8Qv8Q)J(saoF#n;m=dzuZt|jiYmco(SY#86X2De5iEHFphvgLxr&8sQ z7!rc@>3YMybuxD5JNw@bO%aMEeLMTrz;d-|0-p(`au41Z> zhAe~s6Rl!gy-9~Q^ZT>EhvQV0q2AMf?Q(;G(g^!kI9kHse3sc`qgxP`ZMx7=-rtVw z>Il}aa`QkAy59Jp+A9~<6!Gfb@~2 zp}UpM*Z4X}cZcFjK@6b55H{8?GVk7~%i={+@$^`Q&QRQjrjW&M!gq+-}`WAHv z5+M!W7Uy9T@&0%Tc-mq4MEx*R92yvj>-Q^D%6S6l58`tj_gUCPz0T0@kx-h9h9YF# zM8QD$r#jplBoWGAcf~^IXK_%6km8Z^Z7JZd)S~L?IrLAGD?{&%bpMQFf?bD38Fk>O2zCLr;r1J5acs-}IWzG2Bjbe$0B)OL)C5&B-M*YBDs@c#mkigs0 zHJ3~XPbxD=)9)OmG!)MPO=e!5-jA@_5IU5-T_{v;qkv*`A){AIN}$b4E@5<1*SbR$I z6!0RSBX-DRKthKU<}2}C(QgR+x_}{-BAs3fo9k5_a_Z2(SO*UKOV!#k-MJc0YbD-x z*14g;abWn%<+^pdw-(yXc%0-gWe>B|anC9kWW3BF`Fd6#ekL7@va@s|xChu<9A-AU zv}7v^K_DK(V^%KaAd~GXn4?p6Tr3_S_ zUs)@+tSwyovmIo8Ak0Qh&#$hj5YV4-z7^-KuAd3`3;3Bg&XLECyoyE+R40FLojR$_ zrk&=g0Y+5$j>H*WZkCOK$xlu{nTM`6Me@JwX=}mmd6{crq8bdsV0{@3s`Z6<*5cW1 z+k>rsnL^L{mv_}2-XHqzOruAW?#oVpU2rrJb%QU#X#Z8fb+Mc( z&}*E&j-!D^Qc1*ea}Q2(8|si%Kw;A4PDdz6mo+ihyNsrZ<=cRwofaE8HB&YVwiOv{ zVso&K-^>!aG;tq<4QL$sw>R#nlrT03qPQ2}cXk!67MwogYEXW?TzSM#!n9!HT$3fd zsfaON>Huo3Fcz!YFEhfB5J>en8-ZNfv0CSKy`(9H`*KEiT18y;y?I2{KPd$Ld@y)k z`SGDdwPw19yQRKaODx(M>8oo~8`PnI94oWZk=0=f@Uop%6N33XLKq>8hIo|w`vTug z(?7dR?lrrd33o;O`;qr1@q5Z!F%Osj17Fpd-GA}OK7$L#_CCyIiHumr7v&_50~?<{ zcZR$ciB9V^NZvRG;+~>=(;w_RP%?(vgLKu&Wkn0zcEnL{LPUC0HGOg`KyQ8W1d7sZ z0+H~6A}qCo1q3GO>{20vttm7HqaJpkIdJp5NC!TJuV_HVgDNf@)5pT^wkWAhtk#DY zz7Q+dFFf`olkyJ^y(l23$_~4EKpC=DW&l4#SnMfGaXVIy6HMB5jpt+^TZGSk4L$Eh zlVbx?o3KYXk7A${f_?du%Lp`Tz@3@!Cx}>eTGA*dFa^pjhEBFI%@_{;TP_s6_V-CT zC3SS(Gst)QrF70e;A0dO4vXLaK@z;deTKp!Z1k&t2J4A3s)ib4vlQY1d4R$3Svb^k z9&OG-m#R!RPBRg}ekQ;mT(Pf|)VqECFKbK1tMF{MU;C{J3WxV=#L`B+pzs}mII+#4 zzXX=2+V3g;pB})riYDxKQd5=ns54XP4BT}$_+(F}o+gYS!5JnGoPiuF(+pwb;`Zj^ zjv)#og@(;r`V*9}b?=a~X^{_;&3n@A5Qz-vrNzkyb!*8E-mHA5g!(a%<6H0b%@KqZ z4}{b<|LuJ2Wfej561B=PE<=gSk_V0x!T@+~L;l}c9{Bp6`)(DilyfF~vi!ZM`4bRp z7Qy=UvO|%Vx^|YdvU&yo?GH_Ru5cn%P1Jxu&ki4A{k%-VU-~#iYsZ!8dcE)fbIC#nYelB=cWFGQCPbn%OJe zzJ$&aTW=nyQ{-N}LI4=Iqmc#sUpxNH2^a0TVatZu{WC@sHD(E$r$M*zI>4FtsKdL4 z>ZvYEiS}mF3D$eWfRu|4Wu=3<=iI5%F_D%$%?=Ep2R5^Ykq4WN{sgSf(yN~kZX#eq z|E4F_ZXOcHV|PeyVhXOY3SheJUe=#-Yc-)vDH;H6i~XRPD0k$SSlR=S&LAhql8oM| zJ_~2Ny}Ah##Dws3pte`KeDi9jqTeqKA)NRlJ+;WlYI69B@yziqSj<(Xa*7NTh` z1@$Fueu+T1S-8r==CdHox0Xzkwe+#I*#(G?~*lm~YYPmqkwq4RrZjh;s`a?u|bj3rYX@7m&2AP5p69qOsRl zRdlqJ++j4M63G^R-(SN>&_}BjGwB^(>RLGzQ!P8hos^EHZ>an_lENw8ne}SK%@WHD zXlu*9hl&&Xmo5X*B3klmtiVh0s%v~L;8767dtu>GB#G?89A$lGlJ@6)RkfIqGjAzZtwTo{e!zL#9!&hoZim{@BI8Et(n&3jTT0 zVhw?7NHO1Ms+YmAV18V-N^v5FmdSb`BE-!00M(7S{!1UDqbk@lHUM(jk@3a{)WnB% zg6R`tu=h1(VUy@UdG51|UW;G0TJ%fv><#cbbWE4l@uwbl+VEO_jZeoPr5180!?wK^ zkiws&z9`0l^e{0`(o9m1m!mfcm22?yJmEh)752ZsA7a~n5VWjdK1(5BWJZ8l+wq|@ zJ5Ht8WrKqT!r9w5sYoPg8bE=AujQxqYLzn5yRe1_CS|x zUg*Yv23~6!Rb#=8qMt8^O%;Pqom9d=Vz27WltB;w^bwAARaHc5zq0W_G3#zs_ujO@ z?hcwr78i;E!9B)Gihu+qIW~9p-)AJ`PSglh@Cr`zV^?kHIbT&wu443*+8w@);-d&k zA%uGIX@Q#!SYdWlQHngyB_SV(wFSSN^t4V?Su8=oZWFtY;$O8SHOZ!}TJUt|eztrUF%)?iRFmrY4 zpd_}NH<+satqnP0PeuzH9&&hSk>_ZMUxOeFll#&szlibPhlpo#6auVq@EImdvU~T`gl3h zVq1PM@{%6jbQlfeyZwD!4wNVsN27Woo~Sp&4@l`q^6dVah1Z2f{Y~_e{{{#5tIVs# z1m~E+*jqi<60)Ed3?`o>e3|L{^?7qT<%X~x$ERE*xp6dOT@kXV%s@yNFTj#oljiF1 zA$`e3MfF=Id;m`^g9(g6=Va+NM&c$auQ-~ibqCx5=K#cjxQUn(_d(XwJfAz?YZe?u zbyhQY_cb(pNy&b_F&#j-Vcts0@xwGCN@;y#ryfBlz0aW%K|M#)GKFs+I_K_b7ZvHR z_}v#!0w6o~i6Q?!mX<>`tZSLPdRWNwcXL@n7$hoRv>jZKM*MwQB^J7;px`k)bo4P! zZss@d+Ewo#Tm>da+a z4d0JGn)Y`qr5^0Z4%p;wXv^u)*pb?+3bZ9e$z-gr>by!N%( z1?zhj2mjUo#su>Dfx#PgyWRs0b}Huf0uaggHdx#EivyEc+l`WgN52kOb^GYHTu}f@Ou!|5*VbvufNFNPYtEbj4dem+e-h%B+BgIZEnu^0$ z{O*~}sv^W6=;W{F$N{Waf?F7XDgjab2D8A4PP%iv^?m695db<*`$Zt-5^GsUqhsIE zJ14R-Jf=_F$@m)eaEuaay2wC?02M?uP{e6)0pCfWEYFFx5c{pOMzQkIfP!=4GXV%D z?x%uFhf%&G_7=#KD*EchEcQ3hWGF1efdp z{G$g^73h3IS!bmldey2^|FuGakwu!do=?xKbD}_x0xv;v)p?REv)xx2hDMnk&pK|y z^SO&`GRE*$P`G#vT*fq0oC5v9-0y0fHA*9~xKHwH}nE~pku^N)Hsh@ll{z(&&jXz_l(}3z7i=BDo<747Gx4Y zHT+;}Z4rHJ%d?>KF4eY%#}YnixDj+QvlwT#*z-*;X1Q6*wSnf44`FFR9k)vzz3WaMw%2HrM?Bpy|sa_!#c#B%L44CvnI zrTh1Nq}1L24#4n7%#9fROe|P!iGd=JQBMEfEz|mKFZ&l!Wo9Xbr)Ry#4 zf;#avBKV8o7+j@2tZf&Xr#Q4}z*v0xe zi5Iadxfi>cLPl9BjnXMHLreo#v8l5cIBQ$Crt_P_`LU%yEhyCyGO2R}*68VMC3)g} za01c2?6kn*jX3($XdE94?vd*iq$N5A>B50vR6ZS6hu^x*=Y=$-J3|_wL*tdFIwN22 zw>(Zei4rWJc2d;R{DUb{6_a1EB1fexD2pY_Acia$r$}{ z;rr7+3Pw;Pbpn7IvZ%2&hlC0d2a%)wjrfZ7*a(Dilpl)u_ai=N-qIM8UB-4EjF67< z;tfgik6z)K{vs)&gcwKXC&a4*)7Na^6Z0a(K~>Mpiw-Rrs45(k-t>U7#aHca=G z3M{#$eR%l#d*2xt7$T6Fm`X}(o_;wN>E>QT3k(YouLRIK%2&G5031~8(wcetJWh0_ zs!N_!e97z|s&-2Wrl3sZ-_2sPfr$H2Te_j}=u7CWK5ECJ)hHdYWQl2!sxP)Czv4ouE2X88*@H4ysjeX)rv5UU1}{G$4{YPd7`7b%_F9ypfSRO_5Q!^|i*wh_4 zow8p8y?D8*xE|PA%FxJXVDQZkGiuvufz{7e#6)pE>0ddZ4z4T7{Z`Q4-lWe5Di3O_ zbSC9&B>wN_ev@Ggyw6`s5Xs8^6SncwU*@g2c!h`nh+mfaacUPgV_ro27w>vJENsx8 z+nH58SZ7zM%ss|rMG$3=mfa8AcmjTu-(>m`>>+npX6Jmsicx@U+fKF4&ea1u*QY(X z#0CXxK%17P;)a6nH#!t!8r6pHV^;T#1XA_NLzI&VCD)vlf}B;|VmGW0wBrWqeHFR< zWgBkYLF}&KpW5u?o<|XWNz4_{edcf53RA?qpRgK?I0}$I`AI88p@pUKz$M|Zf6@@B zC2X)zkw4Ie_&3}udaxxQkIh!lp=MUf85-t z%J5F7omHKI4e=}-a+M4z5$hBVe7Ptc$MB3lZnQWP(tJY_ z*dP=roSA0J7+gW6g@K@f^gHpa3+4xGxJtXc{@cf`0k;z4iXZC3sQV%dyF%_2bb8vf z65{-RPo?RxFU%*aCr&3l39Svx2?`-2eGx|_R>KEDWv8S7Szm$S@2puc627{G`&*}e zIB%afqx+g0*lY6V@ZS58^(xbg9gnMtThlFrf@)+*ujk%_776YLNoH?a7I(4?9Os&#CW zxT)8$-P`zgiO{I(F-kK!e5?W!4Z_DM&-$!Bsg)%(Fn4AG8U6x|Yz9=67c}e&%f(PuJET=LpWofpI)%spjj_`yRJD|k2O?eSi#pSvQAp?wvLE0tcx&vRn0s(w zmBuW+JahW@!_kSyP>L%%>@!XSD?}Wcr`VQ?Mf2H7AILJ!z-LhaGge*chuweY3^tJQ zEYWSDqfv<2!3hdFjkUc~*>-(iW-&mh!qcR1oxG`@bO{Ru9rj=@wD?loL;RiH)jbtl zY|{8~_%ENv9@;vG#`Ea#W&4TOTh;X-$El+*Hd2%V4Wlg^@ls)#n=2=YDgR{PGJ^KM z76svF)}e__oNZARJlZ>3`zXGb6u{+oHGyVO!kzu;5NneCRyS`^_q$%G=exSV-I>Us zxs(}Oy7BH2_j}6v6(*rP{X;fQa?i-pNfHKHl{i&#Lf{e)xEi_L7@N|Bk@A4gxRc4X zL${DbKK3)q=`w+!t(hE(k9a$69yA|t$URVFv@U9FFNc6TmejDKqY467Mi2y#WFhLz zkoSJvz~>Y~hzA+6A>U--LwC6ght7}wmlY2X4<;EwPV(lRU(m|_>6QT_yoCQcOb<2+ zzJD0r1SBduc$;dUQ4U?OVTFh$8Sa>u781pVB(}+^dT3MRo(C64pk+Sq>-u}O>XGb^ z(z~zyb0jb_wlSmXP`XA*FD3Pist1GMaZFi++TZGAaxXc*zd4jHWn~bhgT+j|+Z=8Uvr1{n^!gG!f9_}w0>!58(` zSqODvT-yko$+d$%G3@`UQ@Pq1Dj3$vl{*QZlNr*sF!5K^2_YfPM&WISU?IM^cj%1k zG73enAAqaX(B>$5w8@QpY1C21T+Gxer?2=2s}3p1t9M|>&-i54Q&+s8j+bQT2}m}W zYuat=>UUK`Z?&t<>-DA$ALN82){n{A*(_?mZp|uKq3~O)rD;+hH7i>HUBN(EH_=yU z#72&)-Ieo&&BBjd4oPx zK6TdDmX?s#)|^yUtth_&XrF@HPdQCrv457_OOf>-VqP%6vdBGM$=r)bp%+RF!{mBE zvFximrzg<-H{qIp>iX1*s}M$RCzQEW^;+qjF<=Rf^-h-OdvnOa%QWSd#7J(RwJ?f# zUoSnX(tp~x#HqPe{=zvz-8h$l$R3vP{|XqdPEzSXIjDr{#v7j5z|~KoGw9ZDy;MNH zDyRe7yVfL(09jcrsrJMVNT?Q9{o7dEa*GlqtqwW>S{`;-!_p`0;x|Ipb;BIDCBtxC z1>a&>#iAs)`9cDkhdgtS&%>~&l!7C`mw${}^fQb(unO5seqek-$$1=m*YebxhB{Qa zv1(qqHKuAndy_UFc(AQfcu6b6@wwN$-1v(>vFmdP`hj*Z`#89>hi;KHUNQEGOarkg#oc;Nuo(xetfKf zTFtLY{W|@EAqoZ<^CK(D74R5GjIjym;7eVN{?GL#v!V*mjnw=Q_kV-JTM zlL-IIVuP7Jem!D#Pe2Xj0P!k;<=@)@RBFAI_={Ut*sKL0WQ_kBe?-G%=&K2&I5sr! zG0e?OMbN8NB|q~V#LkXcdI`%Mq6fQVH&6cxxBmrwNaWyv2Md_me$s%kfD6aD)yegC zISEHP-PJo>36~rN0YL~~&D4>p zf$2HPOV6_ZvDGP)`pwQdTBMJy3|>Uy?QM2ywpfbmtjYq@FZ zqdxMxQCIe@)Kb!XfDA)ANm!g@AR>u1(PIl(k46e-1>%X-SrtX3_gjnAz8kQs2-fu|Y3p&JYA@$gznMdM7|s&V^K}n*ZB%i2jlNRqjBdPFsZC|P z{gBG3k3`*fgcc(Y<=@`)Jf!AFj>M^<1T~>7^=spObV&O-wk|f=l>xH8H@5fB$Y?x^ zzl>$&b#&*^w_f4MtL^$B-#oaNzQ1*PX=$uvN4isMiG9AUQ3nZ4 z3cwH9ifW;8$(3umIHPspEA{C%DchmFfF=+uZI{rI$LC)$by`o z#}^&a-O?Z+-O?xsih!tqh_uq3f}}`@bTBlTb<$Z&cPR}V! zLt$FH`UNakl!QtJ@xc=c-^qdB}yQ$LH(BU5$s@p*8TM!1s`cOS~zars<;fMF;#i%=Z6NO9aN&Vk_RF*JsH7| zebR?2R?$O_J(*7O+{CDI>HAGq-aX%$ZJj1O0Z)k8SSH$5IA7~}<|??-8q;6+NkIXH zk6kR96IvTc7kfm6CuGH9 zudNuY?V%W4dBG=;ZhoabcJ^~~m__qO37yKJdSvu=0*{H+InG;a2@!}CPhi=Ld%3mUlx4K2zn!|qO;U@tC15tIUR~NCEZ{cceRBuWto%dAnLQ@ zK9os`b1%)E&LrtB%4wX=r3XX|wN&${TB{-*?L9+`+GhG1)K4+A2t^LBdR=p83=F;Y ztP=)nCu;~hE*9cXedaU3?IJY1H^3Lqi{hdwN+rdnzmv@VWcBXw9d36%e77j|C>#Y2 zr07S=z1t%iuQ;+8DqST`(#u|P4Q}tqx6>xrUo^~;i1g2TE7XQ#yukVYj%#ZYDzT&Hmw zUSGZt!|mAwK}Zlr1@6@8_)EVzv4tsg2m#sm<6;%UE#nu5vux-P=DWl?4T3|F&Wle8 zY}u((?_U|ru=G5hFONJ&pKw)hm-F7J5#kWcB0vSV-rG&8H*|CIzHfIiGp%VjMcEM2 zMs6*hK%pVuIKsh5gE5sZ^?Xd4?bdmJs*=!~q-nO>cK*~pfu*Jh2NTa8+r;ZkDLjLJ ztII{0_jGTl_XXX`pca^ds#1<^v0%(I@cuXw_(SZ0Ajd`sf)FvdAqYi{E*_Bu_FL4q z|3nW@x>-Jr6Xrc=rjD0s+{wC>q_w^LRXG+_<-L-RWs6qyr=|GR1m5?@8QwyJtG98S zIg9Kl_mkX<5)3af2jU@K!6^zd-=j)FvtoO;EiV5Yg(Av|TpFQq>c%1WB@%+V!lmpM zHW5D4rl^NL7}-^LY3L+o>q=W!g*vBFE-aMs+2`v-TyFGiINh5wNs{AUguDYxR;r*l zzHk(!{nD95k}^WAyE!f!5hKOs3G#+L5&hGRPmWOK6px1#Iq#nMCg(0|1@0h`xRM#F z`Nxw{FHG=at<5}7s6Z*8KyKWcQHpkOp6DcysI?s~iO~)hyjR1s6syNHdoMXtR3^|m ze|4B?-HHcRIueDjZgb0Edybf1!Pj;Kj|`I_VwGk=HEr7Q+4(z7u;41K(F@Tjx}qze z5_1z?yos8OaY=2BHF_hgAm>t$m9oT@^^e*tQKXrye!L+8Ww5Wws z*)Dl1dmOW=)ALaQDeVJZqDwwZTpHE1S2HmAN56}pygAO_eM%f zh|Oo*$0ioIc3SQ`DM_Q}qoX(j@pp~P-IwR633k-HJ=dDN|Kdq3AqVc0F!{;}muoej zV|`g-w^CkE`6&{gbK8pCN4ObW-j$^JUi7MF(tLy|-e++R!}N~b%XL?!Odq0(M6PQm zPUe~9M6ss&I!WUxR;rLhWCc}KjHNWnB)C8AxVD${QDBqqlIF*ex1y<5F%8)-62`nw zavv&0IP$p_V4rt#q7_H=AQS2N@NBVHI?QZVek6{B(@B!knwc#3;lPcHq6;3o6DMi6 z4+nDveOkZNh|JF1t)Cq(q_3oTdfDW?(Opeu^{+HrsluTgN~(0X2!~EmH;i8s48)s% zBG(pyrI|=*9W)50AgoM#&~cX)TuCbK;IF6?MjjC}-}V{9_sHa9CF-9({%oC%A?FjI zln8J0kMJ_Ou;^sf61k z?mC(ELZV?b@59v3T?*6zrm8!S6+VSL=F)_yuO-AY@1oXXtI~8%HtW7HAtblpynkxM zVAN@QWF}2aMDGiWd9D9N+p*efZ$%C(UL<`oTVYZCVpdD`pxDIRB&P!YT2KT&dub~* ziez4DiFQV1J>^S#DTk0v)H#=gsAPiOx3_7Bh5MLRCJPzViWA7 zUu#a$+_+sLQSBDfCaX59qt}0LR``_qYL36#t;Tw`cpEyuujb3UvNuG#wHMT-8g#Yf z5?)^7*ooJZG~fJ4K3&547VU=2DPf<&^7{!kmLr?jP<5b%3U{b+hF)@>X_Bst0YT(> zGzpZwLGJrIW>2ynv>TgTyLcx_34=ucR_7b~h>y;`lQ$&}eQSDFNCMG51=1tLbM|I` zITw8g|FE^Q^Qs%#;_-WEcckR<8@borg@`c{H#d8_7MJV&StJWKPZdnRtY21GOV(<` zanN8TrP*-5qP?K;StoyZg7})L$?XLeyzHmT>7186=A4i;pphsa=Us~X+gC{PFJ0Du zh8wc{qYFid`rf%B($K{t|Ci1c3Bfees)KBirl+$3A-J{gdQeXka;=N0QDpgw)C+dc z5bM`0O`QE-XYbo?ubp>2jMIf6u_cpa^T*VZv|&gG9o&r32;@Rrk#n@i=Co8S4Tbo7 zlgE0ND&bsRdoyNFHG`Y#rdS!2?PW>wnCgu-LUx_K>bJvWqEuzW4^l;3mg)Obc?i~W zN_a!+I5+*+=(uahKM;%Ex_Q@w=*XqLg^AUySE60tGM$33;S2UB=LM0(S#y>t+`G;N z?hcn)wYwUhPxfu_X{{q>V8wb7&)(`nnnx?pO%+Xj>){GJW#7geJV081P^?AIkNR}5 zKF(uwNw2+#FeKS9W(nz1?#+edjR}iexDA5EMees~H!f>@SbY_LmmewY2H(i|!BNZD zpyJluu_=znQ@6XlO`wPGB8`G;nl5%Huk_stf96^3Hyj^P<6yAY(^EX<9kqYIiAkvm zA=Za*2&dxy^+&9I2lf=j_=MOCOZ|+`u3n-?V~DWNLAw>mnYyVvP8XryR^*zl( zq15YW+ewkl&y(bF-W3jT+_5JSoYPsx$RYM(w25e=k%{cznXID_F2_02DQsq@_pTA+ z*`hTuwB5&r%25kk%FWmDt4-&@PkECvnHOSGNjmRP&OUjK5Zr`AKZ5df`&ClIf#2lG zSSOjhvk}kr#8<`dd)oU;EK}EhcnJh`d4Bg3gebar)Ia%&!FVvnYqq@3%8R8?Mcal-(ydn6IowVLX%P$fL&S6Ku|_s}-y6>iFNsL4<($|hZd1NBlQ)3v zjYMF_6r7IyJ4mY&L|-EcbZq%m-(<7UY84F#3?>IA=vi=TKhvmR^? zTz4Ms3eD20WUE@WaWo`Kp40aY8%8HC19})Mv zjBGRnM1RXu>Cvv%P2@a1V~cnG7Tzpl5pHQ?pN`Wi{b`aJLIe*&9|(kIKQp^QdHEA+S8l(1 zHii{(o7p2&T`NZ{{#4}B6G&0{1Cn!SA!6J*BpQToO0JQeL&GM_6)3HF%Ck$}RE!W( zzCVw$#_mBn8oxt+MG!4WVDz|~+%e7Mkt0vVk`}EEc77`gP86!8tBVM|NFlS{vWXqF zs20gmgH%gTm-4ZZ{R;}3-$&WgxdR=9?$-#oB3*(oeGCJuZY z{-G28=hpaxP%FB4%s&z8(Diah4rP?@Lu19WFG(2PWZLXVrxhP5jtB1S`m~{%MQJKf zVV5G7UGbiEmV#%8Vco!P>eFb>K|N>4x+GVqDS$%Uf%kL)whuuUd)e2n5BwEO%)^WmounSTdVtm(D-}x+B>%qd2C6?}gjnk!g zg}2=TV;Q(se$$Nm$;3rF2b})G%P(T7`Tc0tHm@3w4r`jdf+6VH^+t^TK|J^x>)$`^ zQ?Ag(WBp>{g>e>2iMcJkhK$pAc^_Vs-^5kb9&2! zV$b$@B)Z7n*%x7b*-iI4z$6|Tq3BTr&l3?|`;hZh&N(l=(vR6JL6OOji8J0&t%`-L zF(>JxI{8UuizD755mPwV=%?J?&`~n7S{}DrCx6fRNU7m zQH(^QAWzvG$`ZB3=J3nL#PQGJTYkOW7>b05SvP(!S}=+lD?LX{IsM9e{aT@jru4XT ze2&-^=jbC?wa<-XVXUP!Op!+MPkW}F(8oVsTxr4$v6^aXf0IppaG7#`GD};(drOx% z6ahsVZD3{G>p7CVLWy{EMUhv3rGjpkU{^|cXom+vteP_N;IV&)z#XxEqeNkkJD0qI zGr#trOdnI&jqRz$JQAC68OSyQ8?Isu=p^ zGbV0gL^$~4yG&kt3Y+ISdYA3+RQtV(}0lHda9n-jFk&EZTAQ( zuRoo6V}mz%vdXgW*eZ=H`+?B?WA}Y(q=%{xspftkeFKXA10?2CYrW=0xq_gr@P?jlA7Eq+csY zKbnb6#_&)Emv~J|bqgaUDA6N157fHfMNm)7OMCXTYhUTppl$PZK~a{WsB@ih#dQ)h zne)$)luYOa;=Rc=TMOui%Lc@dsZ^ezUAS`_2J2hObd2C|dO6u+%ydz-%KeROt!ajf zw$;~b&uZ5 zHcp_X>M(mKn>u|eH)e0Cu-;>#Q2wj=sCbdnot4fai2=+nCOPiSh}opP^n>P@5wO#P ze%Q%l^yv(X?By6aV@cTOA?8;lG2rQZm$oowFH%}g2Qyp8)}G^?kBE14_%z*oLohE0 zgcRM&ZfCmLd3yV^NdByM?qhZ!i@VVG&jsi zZ)2>Q1VGG5fyFt#{5#>Ie;sXOXRQf&jw?ggcRj{9u0 z!DppO=0avdXfm`MX?(4y9+tZJI(1}#EF{39Q111dNfXCFYq{s^Fs@{VfF<$#6QYu1 z*u;huY97AMo_9bqhJVJ^)kYzFAD{br=OTHS`e#^?He3T0E~L|&V4%z^)WlH6##DrqKJIH+iioICae9yth;Y{|EqFCsxXeG+4i}ESS!2W>_=0u zT_bL^Pa+AZe1R)56S0?HWxa594(u*jddnI zactIA#S1MdmL#b;R^Ji(SRzEl!iKL`Uzj`P7TX-pL3O! z+(XHEa}l0?Y<5mVwd6~s0)x5Qfw7+kNg{HrFYnTI;y5sr*|zqEv=$99z!oy+oa%cpnAVXKV`$>v%jQ=bd-vSYg&1*z zM=6JHsVjD<V}i zOG}jcr2YwMztiNarYn`_+|5{0!36!qsGvRA=~N>OMnGPAeR9`(wisdlxc zn0#d>W_c z;Qd|LQHRt6zbu?;+$1wMZ3!oV_hRun4_AA|P&1i6vL?npO=QETE|!_ht)7|MX{wnD zI*1-cNH0p2FPBP?%+wyumu`MhzSVvE?aL2h6z!)Ev~8};Tim25s*-k=RCe#kMQW+W zx)TwXeDh@|r_vPF{aJG709BfR01SH%b=Q@}kFWmrVsXuiwp<3=b%u zuolJ&n558~z0skRr5}4y@T3H8NLN#Zl=s4t{BA-lVg zoZ#giuIQT7;9h5XOz&u*1Aglu8_l#=zkcV#?fvGhaH(NY?J-+}9OvtVUD_1yo7(i{ z)lzr8wxl-oTg-;|8?>~UH}EE+lI+LJKDMq_6S}zTGUUggQ@M1T$M36wih<1*bG93m z^z(N?(~s>4U+bZ$s%R>m4#O^>f6A{MOpigH)p)Z{JC&2}zH_MTSX)J~Sn9IqnT#OJ z%>IQcG>(xa&Bsa_(E-!=P$nZm#rZl_Sw+nNijHqm>SwaUSUX}ln$5s?JSmnAHd;af z>7;y#Tej;Iv`gz3#&@j-mb@-rey#QBhMLo6C#UrkFE1}~uWuB#>@=0DG7R>COAP#s z=$wd&+ic7P>&>qC4C@XhlPvEC+X<0H2{XOZ@)u0?$Feq@OW1gb^vW?eFv75?1JP&W zYIQiYt2U)SzO4&?)Ykg`v(k#`iiGLIRpmQjc#hOd_6%MpC9QFzwGA7wAG}Cwbx`WA z*JAbu45N*Zz075WH7v|n7Kf-Ly|@?|AA@J;UPu$=T4yn2)ahk?`-74bhfI2|N>oa( zkgJ^pam@~=7b)G5GTk=2N0@hP0y|lNQ|$u3s8|r}UWUc~CR3L52c??G$5+C+Eg#UQ zT|Y&$_n&2xNQ}}V8pAO6%~9tL;jKtSRT!Q{GuJ;}_nyZQAH_k?RLm^BK)jr9^A@$S z+hcvTApN$|Jrol)+zM|zHcHo0!K+SU(sm`6+&3^sa4Hlm8uQ1rK0L{9#w=Ukemv=HY=S)MNgTaD(3DPKt*zvTyMmlUbb3uvh0wdVa6?XWh#m4wkTx zrXCux1YKJ`1Y{k## zRSvU=?qOR3_YFFgOaq0tN;GDR71ahl;Tx@7-BGpg_`}@D-6aUy{GO{!n4@Z>e0_L# z+xtRqGm_-%)V!Suu^&6~ouy9;aJ4J@D}zR88v{Da7$O(c19t3Zh*_>0 z4Dlav-8g?F5E_g-+@NWxQbk;xPoev@WC8!sDN2^z%YJ^gGE}zua=U-JDtB_ItIt-& z6hhXV5OVTLDpe5!l^m(AcHYa^zRPCH)Z0nUHCYB7xOpEoPTxk4qE!UsyS8U@JA1F4 zcFGV5LVS43+O;#=`3YS@u08KLZgxdb1k6xNw(Qe#m5HvyIPd9@d4AA1fF5fSFMVrdIzM}X#^zojv`kafdUeem* zW!>AIC-cImVp6_5&L~Rhd}NXv8RLgd&!FR4D;J-`h@kjxHyi9&_8Zh0p@rQQJCAP% zym;`Gf7OYM38Fq&>Pt!`;((7AJC*A4ZLZ8fP{Jr;9UpsB(|B zQJVJ>*yMEfwan9Rnq!SGnV}G2s-D~w%6i2*xh7B2 zZuu}OJ_eZyJ)ku4^p2nFN>C>$i*DLtwp|NtXRGN(xz;)7WYMWFGLx#B0#}qAQI{^< z4=!hEUr1CuoXx}=?7rRKcjZ2=so=Rh9SSo(8jCzZ6l%xY9fBG%d$b&%`nQv-y5@}O1#Ilu?7DRo9RoZ7!gBDkxP%S!sLhoBd zWo2*J`OK};4rT4TyCxDV_O~lvT7H`i}+zKMCoF8O^L}KWD1^id_mt)*Z0J~8+Wzh#=M8rlJjvy<&tYR z#i!U-8h*#@9kjd}QH$()PRwpD{PSwhqji#XKF7*=grIeQJl9IPHh;U7^6N&tm8RUn zo7klu61EF$jtUL51M(Nb-e%7eey#l46nNilhwjoLqihk`V|Oq0C)fyCZ0?p9KcFvv zsO91xlWT0JC%Do1980e^#X38rtxnYJzO(0>?0t@~ojOsB4msO}d$N+-aS7DV4&GJ? zk(ddS@O!qD9DRx+#l57iIhs(gK*_dEd0lsu{kW zN*2UYj}dEis$%*jyQzIpSto2;DE1ywKln{{yIDnn+Fpi(jaBc&?Tf-%tfMb(o3P

WJi{_ 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 Ha>M@z`igd> diff --git a/GetTrustedInstallerShell.sln b/GetTrustedInstallerShell.sln deleted file mode 100644 index f34dcd6..0000000 --- a/GetTrustedInstallerShell.sln +++ /dev/null @@ -1,31 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31005.135 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GetTrustedInstallerShell", "GetTrustedInstallerShell\GetTrustedInstallerShell.vcxproj", "{2446785E-E78E-45F0-A89E-FEA778C1E51B}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x64.ActiveCfg = Debug|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x64.Build.0 = Debug|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x86.ActiveCfg = Debug|Win32 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Debug|x86.Build.0 = Debug|Win32 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x64.ActiveCfg = Release|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x64.Build.0 = Release|x64 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x86.ActiveCfg = Release|Win32 - {2446785E-E78E-45F0-A89E-FEA778C1E51B}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BAB527F6-C17C-4BF4-9446-F118A022E8D1} - EndGlobalSection -EndGlobal diff --git a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj b/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj deleted file mode 100644 index 53035e2..0000000 --- a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - 16.0 - Win32Proj - {2446785e-e78e-45f0-a89e-fea778c1e51b} - GetTrustedInstallerShell - 10.0 - - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - Application - true - v142 - Unicode - - - Application - false - v142 - true - Unicode - - - - - - - - - - - - - - - - - - - - - true - - - false - - - true - - - false - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - MultiThreaded - - - Console - true - true - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - - - - - \ No newline at end of file diff --git a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj.filters b/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj.filters deleted file mode 100644 index a12df58..0000000 --- a/GetTrustedInstallerShell/GetTrustedInstallerShell.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/GetTrustedInstallerShell/src/main.cpp b/GetTrustedInstallerShell/src/main.cpp deleted file mode 100644 index 9fad99b..0000000 --- a/GetTrustedInstallerShell/src/main.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include - -///

-/// Displays a message, followed by the descriptor for a win32 error code -/// -/// : message to display, precedes error description -/// : win32 error code. optional. -void PrintError(const char* msg, DWORD err = -1); -/// -/// Get a handle to the primary token of a process -/// -/// : target process id. if value is 0, gets token for current process -/// handle to the process' token -HANDLE GetProcessToken(DWORD pid); -/// -/// Duplicate a token with the specified type -/// -/// : target process id -/// : type of token (impersonation or primary) -/// handle to the duplicate token -HANDLE DuplicateProcessToken(DWORD pid, TOKEN_TYPE type); -/// -/// enable or disable the specified privilege -/// -/// : handle to process token -/// : privilege name -/// : TRUE to enable privilege, FALSE to disable -/// win32 error code (0 on success) -DWORD SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege); -/// -/// enable debug privilege for current process -/// -/// true on success -bool GetDebugPrivilege(); -/// -/// Get pid of process with specified name. -/// -/// : name of executable file for process -/// process id -DWORD GetPidByName(const wchar_t* procName); -/// -/// calls TerminateProcess -/// -/// process id of target -/// success -bool TerminateProcess(DWORD pid); - -/// -/// get a shell with trustedinstaller privileges -/// -int main(int argc, char** argv) { -#pragma region get debug privilege - // get debug privilege - if (!GetDebugPrivilege()) { - printf("[-] could not enable debug privilege. please run as a local administrator."); - return -1; - } - printf("[+] enabled debug privilege\n"); -#pragma endregion - -#pragma region get target pid - // pid - DWORD pid; - if (argc == 2) - /* - * use 1st argument as target pid. - * target should be a system process, otherwise impersonating its token will not - * give sufficient permissions to allow accessing the trustedinstaller token - */ - pid = atoi(argv[1]); - else - pid = GetPidByName(L"winlogon.exe"); - if (pid == 0) return -1; // unable to find process (or first argument was not an integer) -#pragma endregion - -#pragma region impersonate system - // duplicate system token as an impersonation token - HANDLE hImpToken = DuplicateProcessToken(pid, TOKEN_TYPE::TokenImpersonation); - if (hImpToken != INVALID_HANDLE_VALUE) printf("[+] process token duplicated\n"); - else { printf("[-] failed to duplicate token\n"); return -1; } - - // use the impersonation token - HANDLE hThread = GetCurrentThread(); - if (!SetThreadToken(&hThread, hImpToken)) { - PrintError("SetThreadToken()", GetLastError()); - return -1; - } - printf("[+] successfully impersonated\n"); - - // don't need these handles anymore - CloseHandle(hThread); - CloseHandle(hImpToken); -#pragma endregion - -#pragma region start trustedinstaller - // get handle to trustedinstaller service - SC_HANDLE hService = OpenServiceW(OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS), L"trustedinstaller", MAXIMUM_ALLOWED); - if (!hService) { - PrintError("OpenServiceW()", GetLastError()); - return -1; - } - // check if service is already running - SERVICE_STATUS_PROCESS ssp = {}; DWORD bytesNeeded; - if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (BYTE*)&ssp, sizeof(ssp), &bytesNeeded)) { - PrintError("QueryServiceStatusEx()", GetLastError()); - return -1; - } - // if running do nothing, otherwise start service and query again - if (ssp.dwCurrentState == SERVICE_RUNNING) { - printf("[+] trustedinstaller service already running\n"); - } - else { - // start - if (!StartServiceW(hService, 0, NULL)) { - PrintError("StartServiceW()", GetLastError()); - return -1; - } - printf("[+] started trustedinstaller service\n"); - - // update ssp (interested in the pid) - if (!QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (BYTE*)&ssp, sizeof(ssp), &bytesNeeded)) { - PrintError("QueryServiceStatusEx()", GetLastError()); - return -1; - } - } - CloseServiceHandle(hService); -#pragma endregion - -#pragma region duplicate trustedinstaller token - // get pid from service status query - printf("[+] pid of trustedinstaller service: %d\n", ssp.dwProcessId); - // duplicate token - HANDLE hTrustedInstallerToken = DuplicateProcessToken(ssp.dwProcessId, TOKEN_TYPE::TokenPrimary); - if (hTrustedInstallerToken != INVALID_HANDLE_VALUE) printf("[+] process token duplicated\n"); - else { printf("[-] failed to duplicate token\n"); return -1; } -#pragma endregion - -#pragma region stop trustedinstaller service - // stop service by killing process, as it does not accept SERVICE_CONTROL_STOP - if (TerminateProcess(ssp.dwProcessId)) - { - printf("[+] stopped trustedinstaller service\n"); - } -#pragma endregion - -#pragma region stop trustedinstaller process - if (TerminateProcess(GetPidByName(L"TrustedInstaller.exe"))) - { - printf("[+] killed trustedinstaller process\n"); - } -#pragma endregion - -#pragma region create process with trustedinstaller token - // start new process with token - STARTUPINFO si = {}; - PROCESS_INFORMATION pi = {}; - BOOL success = CreateProcessWithTokenW(hTrustedInstallerToken, LOGON_NETCREDENTIALS_ONLY, L"C:\\Windows\\System32\\cmd.exe", NULL, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); - if (!success) { - PrintError("CreateProcessWithTokenW()", GetLastError()); - return -1; - } - printf("[+] created cmd process with trustedinstaller token\n"); - CloseHandle(hTrustedInstallerToken); -#pragma endregion - - return 0; -} - -HANDLE GetProcessToken(DWORD pid) { - HANDLE hCurrentProcess = {}; - HANDLE hToken = {}; - // get handle to process - if (pid == 0) - { - hCurrentProcess = GetCurrentProcess(); - } - else - { - hCurrentProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, TRUE, pid); - if (!hCurrentProcess) - { - PrintError("OpenProcess()", GetLastError()); - return INVALID_HANDLE_VALUE; - } - } - // get handle to token - if (!OpenProcessToken(hCurrentProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY, &hToken)) - { - PrintError("OpenProcessToken()", GetLastError()); - CloseHandle(hCurrentProcess); - return INVALID_HANDLE_VALUE; - } - CloseHandle(hCurrentProcess); - return hToken; -} - -HANDLE DuplicateProcessToken(DWORD pid, TOKEN_TYPE tokenType) { - // retrieve token - HANDLE hToken = GetProcessToken(pid); - if (hToken == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; - - // args for DuplicateTokenEx - SECURITY_IMPERSONATION_LEVEL seImpersonateLevel = SecurityImpersonation; - HANDLE hNewToken = {}; - // duplicate the token - if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, seImpersonateLevel, tokenType, &hNewToken)) { - PrintError("DuplicateTokenEx()", GetLastError()); - CloseHandle(hToken); - return INVALID_HANDLE_VALUE; - } - CloseHandle(hToken); - return hNewToken; -} - -void PrintError(const char* msg, DWORD err) { - if (err == -1) { - // only print message - printf(" [-] %s.", msg); - return; - } - // use winapi formatmessage to retrieve descriptor for error code - wchar_t* msgBuf = nullptr; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (wchar_t*)&msgBuf, 0, NULL); - _bstr_t b(msgBuf); const char* c = b; - // print - printf("[-] %s. err: %d %s", msg, err, c); - LocalFree(msgBuf); -} - -bool GetDebugPrivilege() { - // pretty self explanatory - HANDLE hProcess = GetCurrentProcess(); - HANDLE hToken; - if (OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken)) - { - DWORD errCode = SetPrivilege(hToken, SE_DEBUG_NAME, TRUE); - // if errcode is 0 then operation was successful - return errCode == 0; - } - return false; -} - -DWORD SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { - LUID luid; - // get current values for privilege - if (LookupPrivilegeValueW(NULL, lpszPrivilege, &luid)) - { - TOKEN_PRIVILEGES tp; - memset(&tp, 0, sizeof(tp)); - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - // update this field - tp.Privileges[0].Attributes = (bEnablePrivilege) ? SE_PRIVILEGE_ENABLED : 0; - // adjust - AdjustTokenPrivileges(hToken, FALSE, &tp, NULL, (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL); - } - // return error code. 0 on success - return GetLastError(); -} - -DWORD GetPidByName(const wchar_t* procName) { - DWORD procId = 0; - HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - - if (hSnap != INVALID_HANDLE_VALUE) { - PROCESSENTRY32 procEntry; - memset(&procEntry, 0, sizeof(procEntry)); - procEntry.dwSize = sizeof(procEntry); - // iterate through every process, checking if process name matches target - if (Process32First(hSnap, &procEntry)) { - do { - if (!lstrcmpW(procEntry.szExeFile, procName)) { - procId = procEntry.th32ProcessID; - wprintf(L"[+] found process '%s'. pid: %d\n", procName, procId); - break; - } - } while (Process32Next(hSnap, &procEntry)); - } - } - CloseHandle(hSnap); - return procId; -} - -bool TerminateProcess(DWORD pid) -{ - if (pid == 0) return false; - HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - if (hProc == INVALID_HANDLE_VALUE) { - PrintError("OpenProcess()", GetLastError()); - return false; - } - bool flag = true; - if (!TerminateProcess(hProc, 1)) { - PrintError("TerminateProcess()", GetLastError()); - flag = false; - } - CloseHandle(hProc); - return flag; -} \ No newline at end of file diff --git a/LICENSE b/LICENSE index b764521..73417ff 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) 2021 wilszdev - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Pioneer Intergration App + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index aec49ae..c142d1b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,587 @@ -# GetTrustedInstallerShell +# Pioneer Intergration App Kotlin API Library -run as local administrator. -impersonates the trusted installer + + +[![Maven Central](https://img.shields.io/maven-central/v/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin)](https://central.sonatype.com/artifact/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1) +[![javadoc](https://javadoc.io/badge2/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1) + + + +The Pioneer Intergration App Kotlin SDK provides convenient access to the Pioneer Intergration App REST API from applications written in Kotlin. + +It is generated with [Stainless](https://www.stainless.com/). + + + +KDocs are available on [javadoc.io](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1). + + + +## Installation + + + +### Gradle + +```kotlin +implementation("com.pioneer_intergration_app.api:pioneer-intergration-app-kotlin:0.0.1") +``` + +### Maven + +```xml + + com.pioneer_intergration_app.api + pioneer-intergration-app-kotlin + 0.0.1 + +``` + + + +## Requirements + +This library requires Java 8 or later. + +## Usage + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.fromEnv() + +val order: Order = client.store().orders().create() +``` + +## Client configuration + +Configure the client using system properties or environment variables: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.fromEnv() +``` + +Or manually: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .apiKey("My API Key") + .build() +``` + +Or using a combination of the two approaches: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + // Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties + // Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables + .fromEnv() + .apiKey("My API Key") + .build() +``` + +See this table for the available options: + +| Setter | System property | Environment variable | Required | Default value | +| --------- | --------------------------------------- | ----------------------------------- | -------- | --------------------------------------- | +| `apiKey` | `pioneerintergrationapp.petstoreApiKey` | `PETSTORE_API_KEY` | true | - | +| `baseUrl` | `pioneerintergrationapp.baseUrl` | `PIONEER_INTERGRATION_APP_BASE_URL` | true | `"https://petstore3.swagger.io/api/v3"` | + +System properties take precedence over environment variables. + +> [!TIP] +> Don't create more than one client in the same application. Each client has a connection pool and +> thread pools, which are more efficient to share between requests. + +### Modifying configuration + +To temporarily use a modified client configuration, while reusing the same connection and thread pools, call `withOptions()` on any client or service: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient + +val clientWithOptions: PioneerIntergrationAppClient = client.withOptions { + it.baseUrl("https://example.com") + it.maxRetries(42) +} +``` + +The `withOptions()` method does not affect the original client or service. + +## Requests and responses + +To send a request to the Pioneer Intergration App API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Kotlin class. + +For example, `client.store().orders().create(...)` should be called with an instance of `OrderCreateParams`, and it will return an instance of `Order`. + +## Immutability + +Each class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it. + +Each class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy. + +Because each class is immutable, builder modification will _never_ affect already built class instances. + +## Asynchronous execution + +The default client is synchronous. To switch to asynchronous execution, call the `async()` method: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.fromEnv() + +val order: Order = client.async().store().orders().create() +``` + +Or create an asynchronous client from the beginning: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientAsync +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +// Configures using the `pioneerintergrationapp.petstoreApiKey` and `pioneerintergrationapp.baseUrl` system properties +// Or configures using the `PETSTORE_API_KEY` and `PIONEER_INTERGRATION_APP_BASE_URL` environment variables +val client: PioneerIntergrationAppClientAsync = PioneerIntergrationAppOkHttpClientAsync.fromEnv() + +val order: Order = client.store().orders().create() +``` + +The asynchronous client supports the same options as the synchronous one, except most methods are [suspending](https://kotlinlang.org/docs/coroutines-guide.html). + +## Raw responses + +The SDK defines methods that deserialize responses into instances of Kotlin classes. However, these methods don't provide access to the response headers, status code, or the raw response body. + +To access this data, prefix any HTTP method call on a client or service with `withRawResponse()`: + +```kotlin +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse + +val response: HttpResponseFor = client.store().withRawResponse().listInventory() + +val statusCode: Int = response.statusCode() +val headers: Headers = response.headers() +``` + +You can still deserialize the response into an instance of a Kotlin class if needed: + +```kotlin +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse + +val parsedResponse: StoreListInventoryResponse = response.parse() +``` + +## Error handling + +The SDK throws custom unchecked exception types: + +- [`PioneerIntergrationAppServiceException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code: + + | Status | Exception | + | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | + | 400 | [`BadRequestException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt) | + | 401 | [`UnauthorizedException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt) | + | 403 | [`PermissionDeniedException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt) | + | 404 | [`NotFoundException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt) | + | 422 | [`UnprocessableEntityException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt) | + | 429 | [`RateLimitException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt) | + | 5xx | [`InternalServerException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt) | + | others | [`UnexpectedStatusCodeException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt) | + +- [`PioneerIntergrationAppIoException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt): I/O networking errors. + +- [`PioneerIntergrationAppRetryableException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt): Generic error indicating a failure that could be retried by the client. + +- [`PioneerIntergrationAppInvalidDataException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that's supposed to be required, but the API unexpectedly omitted it from the response. + +- [`PioneerIntergrationAppException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class. + +## Logging + +The SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor). + +Enable logging by setting the `PIONEER_INTERGRATION_APP_LOG` environment variable to `info`: + +```sh +export PIONEER_INTERGRATION_APP_LOG=info +``` + +Or to `debug` for more verbose logging: + +```sh +export PIONEER_INTERGRATION_APP_LOG=debug +``` + +## ProGuard and R8 + +Although the SDK uses reflection, it is still usable with [ProGuard](https://github.com/Guardsquare/proguard) and [R8](https://developer.android.com/topic/performance/app-optimization/enable-app-optimization) because `pioneer-intergration-app-kotlin-core` is published with a [configuration file](pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro) containing [keep rules](https://www.guardsquare.com/manual/configuration/usage). + +ProGuard and R8 should automatically detect and use the published rules, but you can also manually copy the keep rules if necessary. + +## Jackson + +The SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default. + +The SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config). + +If the SDK threw an exception, but you're _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) or [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt). + +> [!CAUTION] +> We make no guarantee that the SDK works correctly when the Jackson version check is disabled. + +## Network options + +### Retries + +The SDK automatically retries 2 times by default, with a short exponential backoff between requests. + +Only the following error types are retried: + +- Connection errors (for example, due to a network connectivity problem) +- 408 Request Timeout +- 409 Conflict +- 429 Rate Limit +- 5xx Internal + +The API may also explicitly instruct the SDK to retry or not retry a request. + +To set a custom number of retries, configure the client using the `maxRetries` method: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .maxRetries(4) + .build() +``` + +### Timeouts + +Requests time out after 1 minute by default. + +To set a custom timeout, configure the method call using the `timeout` method: + +```kotlin +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse + +val response: StoreListInventoryResponse = client.store().listInventory(RequestOptions.builder().timeout(Duration.ofSeconds(30)).build()) +``` + +Or configure the default for all method calls at the client level: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import java.time.Duration + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .timeout(Duration.ofSeconds(30)) + .build() +``` + +### Proxies + +To route requests through a proxy, configure the client using the `proxy` method: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import java.net.InetSocketAddress +import java.net.Proxy + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .proxy(Proxy( + Proxy.Type.HTTP, InetSocketAddress( + "https://example.com", 8080 + ) + )) + .build() +``` + +### HTTPS + +> [!NOTE] +> Most applications should not call these methods, and instead use the system defaults. The defaults include +> special optimizations that can be lost if the implementations are modified. + +To configure how HTTPS connections are secured, configure the client using the `sslSocketFactory`, `trustManager`, and `hostnameVerifier` methods: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + // If `sslSocketFactory` is set, then `trustManager` must be set, and vice versa. + .sslSocketFactory(yourSSLSocketFactory) + .trustManager(yourTrustManager) + .hostnameVerifier(yourHostnameVerifier) + .build() +``` + +### Custom HTTP client + +The SDK consists of three artifacts: + +- `pioneer-intergration-app-kotlin-core` + - Contains core SDK logic + - Does not depend on [OkHttp](https://square.github.io/okhttp) + - Exposes [`PioneerIntergrationAppClient`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt), [`PioneerIntergrationAppClientAsync`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt), [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt), and [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), all of which can work with any HTTP client +- `pioneer-intergration-app-kotlin-client-okhttp` + - Depends on [OkHttp](https://square.github.io/okhttp) + - Exposes [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) and [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt), which provide a way to construct [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt) and [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), respectively, using OkHttp +- `pioneer-intergration-app-kotlin` + - Depends on and exposes the APIs of both `pioneer-intergration-app-kotlin-core` and `pioneer-intergration-app-kotlin-client-okhttp` + - Does not have its own logic + +This structure allows replacing the SDK's default HTTP client without pulling in unnecessary dependencies. + +#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html) + +> [!TIP] +> Try the available [network options](#network-options) before replacing the default client. + +To use a customized `OkHttpClient`: + +1. Replace your [`pioneer-intergration-app-kotlin` dependency](#installation) with `pioneer-intergration-app-kotlin-core` +2. Copy `pioneer-intergration-app-kotlin-client-okhttp`'s [`OkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt) class into your code and customize it +3. Construct [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt) or [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), similarly to [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) or [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt), using your customized client + +### Completely custom HTTP client + +To use a completely custom HTTP client: + +1. Replace your [`pioneer-intergration-app-kotlin` dependency](#installation) with `pioneer-intergration-app-kotlin-core` +2. Write a class that implements the [`HttpClient`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt) interface +3. Construct [`PioneerIntergrationAppClientImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt) or [`PioneerIntergrationAppClientAsyncImpl`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt), similarly to [`PioneerIntergrationAppOkHttpClient`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt) or [`PioneerIntergrationAppOkHttpClientAsync`](pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt), using your new client class + +## Undocumented API functionality + +The SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API. + +### Parameters + +To set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +val params: OrderCreateParams = OrderCreateParams.builder() + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") + .putAdditionalBodyProperty("secretProperty", JsonValue.from("42")) + .build() +``` + +These can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods. + +To set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt) object to its setter: + +```kotlin +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +val params: OrderCreateParams = OrderCreateParams.builder().build() +``` + +The most straightforward way to create a [`JsonValue`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt) is using its `from(...)` method: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonValue + +// Create primitive JSON values +val nullValue: JsonValue = JsonValue.from(null) +val booleanValue: JsonValue = JsonValue.from(true) +val numberValue: JsonValue = JsonValue.from(42) +val stringValue: JsonValue = JsonValue.from("Hello World!") + +// Create a JSON array value equivalent to `["Hello", "World"]` +val arrayValue: JsonValue = JsonValue.from(listOf( + "Hello", "World" +)) + +// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }` +val objectValue: JsonValue = JsonValue.from(mapOf( + "a" to 1, "b" to 2 +)) + +// Create an arbitrarily nested JSON equivalent to: +// { +// "a": [1, 2], +// "b": [3, 4] +// } +val complexValue: JsonValue = JsonValue.from(mapOf( + "a" to listOf( + 1, 2 + ), "b" to listOf( + 3, 4 + ) +)) +``` + +Normally a `Builder` class's `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset. + +To forcibly omit a required parameter or property, pass [`JsonMissing`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt): + +```kotlin +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams + +val params: OrderCreateParams = PetCreateParams.builder() + .pet(Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .build()) + .name(JsonMissing.of()) + .build() +``` + +### Response properties + +To access undocumented response properties, call the `_additionalProperties()` method: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonBoolean +import com.pioneer_intergration_app.api.core.JsonNull +import com.pioneer_intergration_app.api.core.JsonNumber +import com.pioneer_intergration_app.api.core.JsonValue + +val additionalProperties: Map = client.store().orders().create(params)._additionalProperties() +val secretPropertyValue: JsonValue = additionalProperties.get("secretProperty") + +val result = when (secretPropertyValue) { + is JsonNull -> "It's null!" + is JsonBoolean -> "It's a boolean!" + is JsonNumber -> "It's a number!" + // Other types include `JsonMissing`, `JsonString`, `JsonArray`, and `JsonObject` + else -> "It's something else!" +} +``` + +To access a property's raw JSON value, which may be undocumented, call its `_` prefixed method: + +```kotlin +import com.pioneer_intergration_app.api.core.JsonField + +val field: JsonField = client.store().orders().create(params)._field() + +if (field.isMissing()) { + // The property is absent from the JSON response +} else if (field.isNull()) { + // The property was set to literal null +} else { + // Check if value was provided as a string + // Other methods include `asNumber()`, `asBoolean()`, etc. + val jsonString: String? = field.asString(); + + // Try to deserialize into a custom type + val myObject: MyClass = field.asUnknown()!!.convert(MyClass::class.java) +} +``` + +### Response validation + +In rare cases, the API may return a response that doesn't match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else. + +By default, the SDK will not throw an exception in this case. It will throw [`PioneerIntergrationAppInvalidDataException`](pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.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()`: + +```kotlin +import com.pioneer_intergration_app.api.models.Order + +val order: Order = client.store().orders().create(params).validate() +``` + +Or configure the method call to validate the response using the `responseValidation` method: + +```kotlin +import com.pioneer_intergration_app.api.models.Order + +val order: Order = client.store().orders().create(RequestOptions.builder().responseValidation(true).build()) +``` + +Or configure the default for all method calls at the client level: + +```kotlin +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient + +val client: PioneerIntergrationAppClient = PioneerIntergrationAppOkHttpClient.builder() + .fromEnv() + .responseValidation(true) + .build() +``` + +## FAQ + +### Why don't you use plain `enum` classes? + +Kotlin `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value. + +### Why do you represent fields using `JsonField` instead of just plain `T`? + +Using `JsonField` enables a few features: + +- Allowing usage of [undocumented API functionality](#undocumented-api-functionality) +- Lazily [validating the API response against the expected shape](#response-validation) +- Representing absent vs explicitly null values + +### Why don't you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)? + +It is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don't want to introduce a breaking change every time we add a field to a class. + +### Why don't you use checked exceptions? + +Checked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason. + +Checked exceptions: + +- Are verbose to handle +- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error +- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function) +- Don't play well with lambdas (also due to the function coloring problem) + +## Semantic versioning + +This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: + +1. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_ +2. Changes that we do not expect to impact the vast majority of users in practice. + +We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience. + +We are keen for your feedback; please open an [issue](https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell/issues) with questions, bugs, or suggestions. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..21f51dc --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,23 @@ +# Security Policy + +## Reporting Security Issues + +This SDK is generated by [Stainless Software Inc](http://stainless.com). Stainless takes security seriously, and encourages you to report any security vulnerability promptly so that appropriate action can be taken. + +To report a security issue, please contact the Stainless team at security@stainless.com. + +## Responsible Disclosure + +We appreciate the efforts of security researchers and individuals who help us maintain the security of +SDKs we generate. If you believe you have found a security vulnerability, please adhere to responsible +disclosure practices by allowing us a reasonable amount of time to investigate and address the issue +before making any information public. + +## Reporting Non-SDK Related Security Issues + +If you encounter security issues that are not directly related to SDKs but pertain to the services +or products provided by Pioneer Intergration App, please follow the respective company's security reporting guidelines. + +--- + +Thank you for helping us keep the SDKs and systems they interact with secure. diff --git a/bin/check-release-environment b/bin/check-release-environment new file mode 100644 index 0000000..3a6a7b4 --- /dev/null +++ b/bin/check-release-environment @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +errors=() + +if [ -z "${SONATYPE_USERNAME}" ]; then + errors+=("The SONATYPE_USERNAME secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +if [ -z "${SONATYPE_PASSWORD}" ]; then + errors+=("The SONATYPE_PASSWORD secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +if [ -z "${GPG_SIGNING_KEY}" ]; then + errors+=("The GPG_SIGNING_KEY secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +if [ -z "${GPG_SIGNING_PASSWORD}" ]; then + errors+=("The GPG_SIGNING_PASSWORD secret has not been set. Please set it in either this repository's secrets or your organization secrets") +fi + +lenErrors=${#errors[@]} + +if [[ lenErrors -gt 0 ]]; then + echo -e "Found the following errors in the release environment:\n" + + for error in "${errors[@]}"; do + echo -e "- $error\n" + done + + exit 1 +fi + +echo "The environment is ready to push releases!" diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..90bdf0a --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,49 @@ +plugins { + id("io.github.gradle-nexus.publish-plugin") version "1.1.0" + id("org.jetbrains.dokka") version "2.0.0" +} + +repositories { + mavenCentral() +} + +allprojects { + group = "com.pioneer_intergration_app.api" + version = "0.0.1" // x-release-please-version +} + +subprojects { + // These are populated with dependencies by `buildSrc` scripts. + tasks.register("format") { + group = "Verification" + description = "Formats all source files." + } + tasks.register("lint") { + group = "Verification" + description = "Verifies all source files are formatted." + } + apply(plugin = "org.jetbrains.dokka") +} + +subprojects { + apply(plugin = "org.jetbrains.dokka") +} + +// Avoid race conditions between `dokkaHtmlCollector` and `dokkaJavadocJar` tasks +tasks.named("dokkaHtmlCollector").configure { + subprojects.flatMap { it.tasks } + .filter { it.project.name != "pioneer-intergration-app-kotlin" && it.name == "dokkaJavadocJar" } + .forEach { mustRunAfter(it) } +} + +nexusPublishing { + repositories { + sonatype { + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + + username.set(System.getenv("SONATYPE_USERNAME")) + password.set(System.getenv("SONATYPE_PASSWORD")) + } + } +} diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts new file mode 100644 index 0000000..0b14135 --- /dev/null +++ b/buildSrc/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + `kotlin-dsl` + kotlin("jvm") version "1.9.20" +} + +repositories { + gradlePluginPortal() +} + +dependencies { + implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20") +} diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.java.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.java.gradle.kts new file mode 100644 index 0000000..81d5d32 --- /dev/null +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.java.gradle.kts @@ -0,0 +1,136 @@ +import org.gradle.api.tasks.testing.logging.TestExceptionFormat + +plugins { + `java-library` +} + +repositories { + mavenCentral() +} + +configure { + withJavadocJar() + withSourcesJar() +} + +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } + + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +tasks.withType().configureEach { + options.compilerArgs.add("-Werror") + options.release.set(8) +} + +tasks.named("javadocJar") { + setZip64(true) +} + +tasks.named("jar") { + manifest { + attributes(mapOf( + "Implementation-Title" to project.name, + "Implementation-Version" to project.version + )) + } +} + +tasks.withType().configureEach { + useJUnitPlatform() + + // Run tests in parallel to some degree. + maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1) + forkEvery = 100 + + testLogging { + exceptionFormat = TestExceptionFormat.FULL + } +} + +val palantir by configurations.creating +dependencies { + palantir("com.palantir.javaformat:palantir-java-format:2.73.0") +} + +fun registerPalantir( + name: String, + description: String, +) { + val javaName = "${name}Java" + tasks.register(javaName) { + group = "Verification" + this.description = description + + classpath = palantir + mainClass = "com.palantir.javaformat.java.Main" + + // Avoid an `IllegalAccessError` on Java 9+. + jvmArgs( + "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "--add-exports", "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + ) + + // Use paths relative to the current module. + val argumentFile = + project.layout.buildDirectory.file("palantir-$name-args.txt").get().asFile + val lastRunTimeFile = + project.layout.buildDirectory.file("palantir-$name-last-run.txt").get().asFile + + // Read the time when this task was last executed for this module (if ever). + val lastRunTime = lastRunTimeFile.takeIf { it.exists() }?.readText()?.toLongOrNull() ?: 0L + + // Use a `fileTree` relative to the module's source directory. + val javaFiles = project.fileTree("src") { include("**/*.java") } + + // Determine if any files need to be formatted or linted and continue only if there is at least + // one file. + onlyIf { javaFiles.any { it.lastModified() > lastRunTime } } + + inputs.files(javaFiles) + + doFirst { + // Create the argument file and set the preferred formatting style. + argumentFile.parentFile.mkdirs() + argumentFile.writeText("--palantir\n") + + if (name == "lint") { + // For lint, do a dry run, so no files are modified. Set the exit code to 1 (instead of + // the default 0) if any files need to be formatted, indicating that linting has failed. + argumentFile.appendText("--dry-run\n") + argumentFile.appendText("--set-exit-if-changed\n") + } else { + // `--dry-run` and `--replace` (for in-place formatting) are mutually exclusive. + argumentFile.appendText("--replace\n") + } + + // Write the modified files to the argument file. + javaFiles.filter { it.lastModified() > lastRunTime } + .forEach { argumentFile.appendText("${it.absolutePath}\n") } + } + + doLast { + // Record the last execution time for later up-to-date checking. + lastRunTimeFile.writeText(System.currentTimeMillis().toString()) + } + + // Pass the argument file using the @ symbol + args = listOf("@${argumentFile.absolutePath}") + + outputs.upToDateWhen { javaFiles.none { it.lastModified() > lastRunTime } } + } + + tasks.named(name) { + dependsOn(tasks.named(javaName)) + } +} + +registerPalantir(name = "format", description = "Formats all Java source files.") +registerPalantir(name = "lint", description = "Verifies all Java source files are formatted.") diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts new file mode 100644 index 0000000..7a74390 --- /dev/null +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts @@ -0,0 +1,106 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion + +plugins { + id("pioneer-intergration-app.java") + kotlin("jvm") +} + +repositories { + mavenCentral() +} + +kotlin { + jvmToolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } + + compilerOptions { + freeCompilerArgs = listOf( + "-Xjvm-default=all", + "-Xjdk-release=1.8", + // Suppress deprecation warnings because we may still reference and test deprecated members. + // TODO: Replace with `-Xsuppress-warning=DEPRECATION` once we use Kotlin compiler 2.1.0+. + "-nowarn", + ) + jvmTarget.set(JvmTarget.JVM_1_8) + languageVersion.set(KotlinVersion.KOTLIN_1_8) + apiVersion.set(KotlinVersion.KOTLIN_1_8) + coreLibrariesVersion = "1.8.0" + } +} + +tasks.withType().configureEach { + systemProperty("junit.jupiter.execution.parallel.enabled", true) + systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent") +} + +val ktfmt by configurations.creating +dependencies { + ktfmt("com.facebook:ktfmt:0.56") +} + +fun registerKtfmt( + name: String, + description: String, +) { + val kotlinName = "${name}Kotlin" + tasks.register(kotlinName) { + group = "Verification" + this.description = description + + classpath = ktfmt + mainClass = "com.facebook.ktfmt.cli.Main" + + // Use paths relative to the current module. + val argumentFile = project.layout.buildDirectory.file("ktfmt-$name-args.txt").get().asFile + val lastRunTimeFile = + project.layout.buildDirectory.file("ktfmt-$name-last-run.txt").get().asFile + + // Read the time when this task was last executed for this module (if ever). + val lastRunTime = lastRunTimeFile.takeIf { it.exists() }?.readText()?.toLongOrNull() ?: 0L + + // Use a `fileTree` relative to the module's source directory. + val kotlinFiles = project.fileTree("src") { include("**/*.kt") } + + // Determine if any files need to be formatted or linted and continue only if there is at least + // one file (otherwise Ktfmt will fail). + onlyIf { kotlinFiles.any { it.lastModified() > lastRunTime } } + + inputs.files(kotlinFiles) + + doFirst { + // Create the argument file and set the preferred formatting style. + argumentFile.parentFile.mkdirs() + argumentFile.writeText("--kotlinlang-style\n") + + if (name == "lint") { + // For lint, do a dry run, so no files are modified. Set the exit code to 1 (instead of + // the default 0) if any files need to be formatted, indicating that linting has failed. + argumentFile.appendText("--dry-run\n") + argumentFile.appendText("--set-exit-if-changed\n") + } + + // Write the modified files to the argument file. + kotlinFiles.filter { it.lastModified() > lastRunTime } + .forEach { argumentFile.appendText("${it.absolutePath}\n") } + } + + doLast { + // Record the last execution time for later up-to-date checking. + lastRunTimeFile.writeText(System.currentTimeMillis().toString()) + } + + // Pass the argument file using the @ symbol + args = listOf("@${argumentFile.absolutePath}") + + outputs.upToDateWhen { kotlinFiles.none { it.lastModified() > lastRunTime } } + } + + tasks.named(name) { + dependsOn(tasks.named(kotlinName)) + } +} + +registerKtfmt(name = "format", description = "Formats all Kotlin source files.") +registerKtfmt(name = "lint", description = "Verifies all Kotlin source files are formatted.") diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts new file mode 100644 index 0000000..d5c0f65 --- /dev/null +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts @@ -0,0 +1,60 @@ +plugins { + `maven-publish` + signing +} + +configure { + publications { + register("maven") { + from(components["java"]) + + pom { + name.set("OpenAPI 3.0 Pet Store") + description.set("This is a sample Pet Store Server based on the OpenAPI 3.0 specification.") + url.set("https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell") + + licenses { + license { + name.set("Apache-2.0") + } + } + + developers { + developer { + name.set("Pioneer Intergration App") + } + } + + scm { + connection.set("scm:git:git://github.com/ummitsmerogers-droid/GetTrustedInstallerShell.git") + developerConnection.set("scm:git:git://github.com/ummitsmerogers-droid/GetTrustedInstallerShell.git") + url.set("https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell") + } + + versionMapping { + allVariants { + fromResolutionResult() + } + } + } + } + } +} + +signing { + val signingKeyId = System.getenv("GPG_SIGNING_KEY_ID")?.ifBlank { null } + val signingKey = System.getenv("GPG_SIGNING_KEY")?.ifBlank { null } + val signingPassword = System.getenv("GPG_SIGNING_PASSWORD")?.ifBlank { null } + if (signingKey != null && signingPassword != null) { + useInMemoryPgpKeys( + signingKeyId, + signingKey, + signingPassword, + ) + sign(publishing.publications["maven"]) + } +} + +tasks.named("publish") { + dependsOn(":closeAndReleaseSonatypeStagingRepository") +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..6680f9c --- /dev/null +++ b/gradle.properties @@ -0,0 +1,18 @@ +org.gradle.caching=true +org.gradle.configuration-cache=true +org.gradle.parallel=true +org.gradle.daemon=false +# These options improve our compilation and test performance. They are inherited by the Kotlin daemon. +org.gradle.jvmargs=\ + -Xms2g \ + -Xmx8g \ + -XX:+UseParallelGC \ + -XX:InitialCodeCacheSize=256m \ + -XX:ReservedCodeCacheSize=1G \ + -XX:MetaspaceSize=512m \ + -XX:MaxMetaspaceSize=2G \ + -XX:TieredStopAtLevel=1 \ + -XX:GCTimeRatio=4 \ + -XX:CICompilerCount=4 \ + -XX:+OptimizeStringConcat \ + -XX:+UseStringDeduplication diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..a4b76b9530d66f5e68d973ea569d8e19de379189 GIT binary patch literal 43583 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 yu?e%!_ptzGB|8GrCfu%p?(_ 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 GZ~q4|mN%#X literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cea7a79 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..f3b75f3 --- /dev/null +++ b/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9b42019 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts b/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts new file mode 100644 index 0000000..26042a9 --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("pioneer-intergration-app.publish") +} + +dependencies { + api(project(":pioneer-intergration-app-kotlin-core")) + + implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") + + testImplementation(kotlin("test")) + testImplementation("org.assertj:assertj-core:3.25.3") +} diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt new file mode 100644 index 0000000..d10caae --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt @@ -0,0 +1,254 @@ +package com.pioneer_intergration_app.api.client.okhttp + +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.Timeout +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpRequestBody +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppIoException +import java.io.IOException +import java.io.InputStream +import java.net.Proxy +import java.time.Duration +import javax.net.ssl.HostnameVerifier +import javax.net.ssl.SSLSocketFactory +import javax.net.ssl.X509TrustManager +import kotlinx.coroutines.suspendCancellableCoroutine +import okhttp3.Call +import okhttp3.Callback +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.MediaType +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.Request +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import okhttp3.logging.HttpLoggingInterceptor +import okio.BufferedSink + +class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpClient) : + HttpClient { + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { + val call = newCall(request, requestOptions) + + return try { + call.execute().toResponse() + } catch (e: IOException) { + throw PioneerIntergrationAppIoException("Request failed", e) + } finally { + request.body?.close() + } + } + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + val call = newCall(request, requestOptions) + + return try { + call.executeAsync().toResponse() + } catch (e: IOException) { + throw PioneerIntergrationAppIoException("Request failed", e) + } finally { + request.body?.close() + } + } + + override fun close() { + okHttpClient.dispatcher.executorService.shutdown() + okHttpClient.connectionPool.evictAll() + okHttpClient.cache?.close() + } + + private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call { + val clientBuilder = okHttpClient.newBuilder() + + val logLevel = + when (System.getenv("PIONEER_INTERGRATION_APP_LOG")?.lowercase()) { + "info" -> HttpLoggingInterceptor.Level.BASIC + "debug" -> HttpLoggingInterceptor.Level.BODY + else -> null + } + if (logLevel != null) { + clientBuilder.addNetworkInterceptor( + HttpLoggingInterceptor().setLevel(logLevel).apply { redactHeader("api_key") } + ) + } + + requestOptions.timeout?.let { + clientBuilder + .connectTimeout(it.connect()) + .readTimeout(it.read()) + .writeTimeout(it.write()) + .callTimeout(it.request()) + } + + val client = clientBuilder.build() + return client.newCall(request.toRequest(client)) + } + + private suspend fun Call.executeAsync(): Response = + suspendCancellableCoroutine { continuation -> + continuation.invokeOnCancellation { this.cancel() } + + enqueue( + object : Callback { + override fun onFailure(call: Call, e: IOException) { + continuation.resumeWith(Result.failure(e)) + } + + override fun onResponse(call: Call, response: Response) { + continuation.resumeWith(Result.success(response)) + } + } + ) + } + + 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 { + fun builder() = Builder() + } + + class Builder internal constructor() { + + private var timeout: Timeout = Timeout.default() + private var proxy: Proxy? = null + private var sslSocketFactory: SSLSocketFactory? = null + private var trustManager: X509TrustManager? = null + private var hostnameVerifier: HostnameVerifier? = null + + fun timeout(timeout: Timeout) = apply { this.timeout = timeout } + + fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build()) + + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { + this.sslSocketFactory = sslSocketFactory + } + + fun trustManager(trustManager: X509TrustManager?) = apply { + this.trustManager = trustManager + } + + fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply { + this.hostnameVerifier = hostnameVerifier + } + + fun build(): OkHttpClient = + OkHttpClient( + okhttp3.OkHttpClient.Builder() + .connectTimeout(timeout.connect()) + .readTimeout(timeout.read()) + .writeTimeout(timeout.write()) + .callTimeout(timeout.request()) + .proxy(proxy) + .apply { + val sslSocketFactory = sslSocketFactory + val trustManager = trustManager + if (sslSocketFactory != null && trustManager != null) { + sslSocketFactory(sslSocketFactory, trustManager) + } else { + check((sslSocketFactory != null) == (trustManager != null)) { + "Both or none of `sslSocketFactory` and `trustManager` must be set, but only one was set" + } + } + + hostnameVerifier?.let(::hostnameVerifier) + } + .build() + .apply { + // We usually make all our requests to the same host so it makes sense to + // raise the per-host limit to the overall limit. + dispatcher.maxRequestsPerHost = dispatcher.maxRequests + } + ) + } +} diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt new file mode 100644 index 0000000..b225e43 --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt @@ -0,0 +1,289 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client.okhttp + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientImpl +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.core.Timeout +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.jsonMapper +import java.net.Proxy +import java.time.Clock +import java.time.Duration +import javax.net.ssl.HostnameVerifier +import javax.net.ssl.SSLSocketFactory +import javax.net.ssl.X509TrustManager + +/** + * A class that allows building an instance of [PioneerIntergrationAppClient] with [OkHttpClient] as + * the underlying [HttpClient]. + */ +class PioneerIntergrationAppOkHttpClient private constructor() { + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PioneerIntergrationAppClient]. + */ + fun builder() = Builder() + + /** + * Returns a client configured using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv(): PioneerIntergrationAppClient = builder().fromEnv().build() + } + + /** A builder for [PioneerIntergrationAppOkHttpClient]. */ + class Builder internal constructor() { + + private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var proxy: Proxy? = null + private var sslSocketFactory: SSLSocketFactory? = null + private var trustManager: X509TrustManager? = null + private var hostnameVerifier: HostnameVerifier? = null + + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + + /** + * The socket factory used to secure HTTPS connections. + * + * If this is set, then [trustManager] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { + this.sslSocketFactory = sslSocketFactory + } + + /** + * The trust manager used to secure HTTPS connections. + * + * If this is set, then [sslSocketFactory] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun trustManager(trustManager: X509TrustManager?) = apply { + this.trustManager = trustManager + } + + /** + * The verifier used to confirm that response certificates apply to requested hostnames for + * HTTPS connections. + * + * If unset, then a default hostname verifier is used. + */ + fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply { + this.hostnameVerifier = hostnameVerifier + } + + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee + * that the SDK will work correctly when using an incompatible Jackson version. + */ + fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply { + clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility) + } + + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) } + + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { clientOptions.clock(clock) } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) } + + /** + * Whether to call `validate` on every response before returning it. + * + * 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 { + clientOptions.responseValidation(responseValidation) + } + + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) } + + /** + * Sets the maximum time allowed for a complete HTTP call, not including retries. + * + * See [Timeout.request] for more details. + * + * For fine-grained control, pass a [Timeout] object. + */ + fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) } + + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + + fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) } + + fun headers(headers: Headers) = apply { clientOptions.headers(headers) } + + fun headers(headers: Map>) = apply { + clientOptions.headers(headers) + } + + fun putHeader(name: String, value: String) = apply { clientOptions.putHeader(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { + clientOptions.putHeaders(name, values) + } + + fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) } + + fun putAllHeaders(headers: Map>) = apply { + clientOptions.putAllHeaders(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { + clientOptions.replaceHeaders(name, value) + } + + fun replaceHeaders(name: String, values: Iterable) = apply { + clientOptions.replaceHeaders(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + clientOptions.replaceAllHeaders(headers) + } + + fun removeHeaders(name: String) = apply { clientOptions.removeHeaders(name) } + + fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) } + + fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) } + + fun queryParams(queryParams: Map>) = apply { + clientOptions.queryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { + clientOptions.putQueryParam(key, value) + } + + fun putQueryParams(key: String, values: Iterable) = apply { + clientOptions.putQueryParams(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + clientOptions.replaceQueryParams(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + clientOptions.replaceQueryParams(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun removeQueryParams(key: String) = apply { clientOptions.removeQueryParams(key) } + + fun removeAllQueryParams(keys: Set) = apply { + clientOptions.removeAllQueryParams(keys) + } + + /** + * Updates configuration using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv() = apply { clientOptions.fromEnv() } + + /** + * Returns an immutable instance of [PioneerIntergrationAppClient]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PioneerIntergrationAppClient = + PioneerIntergrationAppClientImpl( + clientOptions + .httpClient( + OkHttpClient.builder() + .timeout(clientOptions.timeout()) + .proxy(proxy) + .sslSocketFactory(sslSocketFactory) + .trustManager(trustManager) + .hostnameVerifier(hostnameVerifier) + .build() + ) + .build() + ) + } +} diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt new file mode 100644 index 0000000..df9934e --- /dev/null +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt @@ -0,0 +1,290 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client.okhttp + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientAsync +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClientAsyncImpl +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.core.Timeout +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.jsonMapper +import java.net.Proxy +import java.time.Clock +import java.time.Duration +import javax.net.ssl.HostnameVerifier +import javax.net.ssl.SSLSocketFactory +import javax.net.ssl.X509TrustManager + +/** + * A class that allows building an instance of [PioneerIntergrationAppClientAsync] with + * [OkHttpClient] as the underlying [HttpClient]. + */ +class PioneerIntergrationAppOkHttpClientAsync private constructor() { + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [PioneerIntergrationAppClientAsync]. + */ + fun builder() = Builder() + + /** + * Returns a client configured using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv(): PioneerIntergrationAppClientAsync = builder().fromEnv().build() + } + + /** A builder for [PioneerIntergrationAppOkHttpClientAsync]. */ + class Builder internal constructor() { + + private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var proxy: Proxy? = null + private var sslSocketFactory: SSLSocketFactory? = null + private var trustManager: X509TrustManager? = null + private var hostnameVerifier: HostnameVerifier? = null + + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + + /** + * The socket factory used to secure HTTPS connections. + * + * If this is set, then [trustManager] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { + this.sslSocketFactory = sslSocketFactory + } + + /** + * The trust manager used to secure HTTPS connections. + * + * If this is set, then [sslSocketFactory] must also be set. + * + * If unset, then the system default is used. Most applications should not call this method, + * and instead use the system default. The default include special optimizations that can be + * lost if the implementation is modified. + */ + fun trustManager(trustManager: X509TrustManager?) = apply { + this.trustManager = trustManager + } + + /** + * The verifier used to confirm that response certificates apply to requested hostnames for + * HTTPS connections. + * + * If unset, then a default hostname verifier is used. + */ + fun hostnameVerifier(hostnameVerifier: HostnameVerifier?) = apply { + this.hostnameVerifier = hostnameVerifier + } + + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee + * that the SDK will work correctly when using an incompatible Jackson version. + */ + fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply { + clientOptions.checkJacksonVersionCompatibility(checkJacksonVersionCompatibility) + } + + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { clientOptions.sleeper(sleeper) } + + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { clientOptions.clock(clock) } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(baseUrl: String?) = apply { clientOptions.baseUrl(baseUrl) } + + /** + * Whether to call `validate` on every response before returning it. + * + * 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 { + clientOptions.responseValidation(responseValidation) + } + + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + fun timeout(timeout: Timeout) = apply { clientOptions.timeout(timeout) } + + /** + * Sets the maximum time allowed for a complete HTTP call, not including retries. + * + * See [Timeout.request] for more details. + * + * For fine-grained control, pass a [Timeout] object. + */ + fun timeout(timeout: Duration) = apply { clientOptions.timeout(timeout) } + + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + fun maxRetries(maxRetries: Int) = apply { clientOptions.maxRetries(maxRetries) } + + fun apiKey(apiKey: String) = apply { clientOptions.apiKey(apiKey) } + + fun headers(headers: Headers) = apply { clientOptions.headers(headers) } + + fun headers(headers: Map>) = apply { + clientOptions.headers(headers) + } + + fun putHeader(name: String, value: String) = apply { clientOptions.putHeader(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { + clientOptions.putHeaders(name, values) + } + + fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) } + + fun putAllHeaders(headers: Map>) = apply { + clientOptions.putAllHeaders(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { + clientOptions.replaceHeaders(name, value) + } + + fun replaceHeaders(name: String, values: Iterable) = apply { + clientOptions.replaceHeaders(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + clientOptions.replaceAllHeaders(headers) + } + + fun removeHeaders(name: String) = apply { clientOptions.removeHeaders(name) } + + fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) } + + fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) } + + fun queryParams(queryParams: Map>) = apply { + clientOptions.queryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { + clientOptions.putQueryParam(key, value) + } + + fun putQueryParams(key: String, values: Iterable) = apply { + clientOptions.putQueryParams(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + clientOptions.putAllQueryParams(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + clientOptions.replaceQueryParams(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + clientOptions.replaceQueryParams(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + clientOptions.replaceAllQueryParams(queryParams) + } + + fun removeQueryParams(key: String) = apply { clientOptions.removeQueryParams(key) } + + fun removeAllQueryParams(keys: Set) = apply { + clientOptions.removeAllQueryParams(keys) + } + + /** + * Updates configuration using system properties and environment variables. + * + * @see ClientOptions.Builder.fromEnv + */ + fun fromEnv() = apply { clientOptions.fromEnv() } + + /** + * Returns an immutable instance of [PioneerIntergrationAppClientAsync]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PioneerIntergrationAppClientAsync = + PioneerIntergrationAppClientAsyncImpl( + clientOptions + .httpClient( + OkHttpClient.builder() + .timeout(clientOptions.timeout()) + .proxy(proxy) + .sslSocketFactory(sslSocketFactory) + .trustManager(trustManager) + .hostnameVerifier(hostnameVerifier) + .build() + ) + .build() + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/build.gradle.kts b/pioneer-intergration-app-kotlin-core/build.gradle.kts new file mode 100644 index 0000000..07d1933 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/build.gradle.kts @@ -0,0 +1,42 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("pioneer-intergration-app.publish") +} + +configurations.all { + resolutionStrategy { + // Compile and test against a lower Jackson version to ensure we're compatible with it. + // We publish with a higher version (see below) to ensure users depend on a secure version by default. + force("com.fasterxml.jackson.core:jackson-core:2.13.4") + force("com.fasterxml.jackson.core:jackson-databind:2.13.4") + force("com.fasterxml.jackson.core:jackson-annotations:2.13.4") + force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.4") + force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4") + force("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + } +} + +dependencies { + api("com.fasterxml.jackson.core:jackson-core:2.18.2") + api("com.fasterxml.jackson.core:jackson-databind:2.18.2") + api("com.google.errorprone:error_prone_annotations:2.33.0") + + implementation("com.fasterxml.jackson.core:jackson-annotations:2.18.2") + 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") + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") + + testImplementation(kotlin("test")) + testImplementation(project(":pioneer-intergration-app-kotlin-client-okhttp")) + testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2") + testImplementation("org.assertj:assertj-core:3.25.3") + 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") + testImplementation("org.mockito:mockito-core:5.14.2") + testImplementation("org.mockito:mockito-junit-jupiter:5.14.2") + testImplementation("org.mockito.kotlin:mockito-kotlin:4.1.0") +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt new file mode 100644 index 0000000..2f4ee60 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClient.kt @@ -0,0 +1,86 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.services.blocking.PetService +import com.pioneer_intergration_app.api.services.blocking.StoreService +import com.pioneer_intergration_app.api.services.blocking.UserService + +/** + * A client for interacting with the Pioneer Intergration App REST API synchronously. You can also + * switch to asynchronous execution via the [async] method. + * + * This client performs best when you create a single instance and reuse it for all interactions + * with the REST API. This is because each client holds its own connection pool and thread pools. + * Reusing connections and threads reduces latency and saves memory. The client also handles rate + * limiting per client. This means that creating and using multiple instances at the same time will + * not respect rate limits. + * + * The threads and connections that are held will be released automatically if they remain idle. But + * if you are writing an application that needs to aggressively release unused resources, then you + * may call [close]. + */ +interface PioneerIntergrationAppClient { + + /** + * Returns a version of this client that uses asynchronous execution. + * + * The returned client shares its resources, like its connection pool and thread pools, with + * this client. + */ + fun async(): PioneerIntergrationAppClientAsync + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PioneerIntergrationAppClient + + fun pets(): PetService + + fun store(): StoreService + + fun users(): UserService + + /** + * Closes this client, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client is long-lived and + * usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default HTTP client + * automatically releases threads and connections if they remain idle, but if you are writing an + * application that needs to aggressively release unused resources, then you may call this + * method. + */ + fun close() + + /** + * A view of [PioneerIntergrationAppClient] that provides access to raw HTTP responses for each + * method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClient.WithRawResponse + + fun pets(): PetService.WithRawResponse + + fun store(): StoreService.WithRawResponse + + fun users(): UserService.WithRawResponse + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt new file mode 100644 index 0000000..5777d3f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsync.kt @@ -0,0 +1,86 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.services.async.PetServiceAsync +import com.pioneer_intergration_app.api.services.async.StoreServiceAsync +import com.pioneer_intergration_app.api.services.async.UserServiceAsync + +/** + * A client for interacting with the Pioneer Intergration App REST API asynchronously. You can also + * switch to synchronous execution via the [sync] method. + * + * This client performs best when you create a single instance and reuse it for all interactions + * with the REST API. This is because each client holds its own connection pool and thread pools. + * Reusing connections and threads reduces latency and saves memory. The client also handles rate + * limiting per client. This means that creating and using multiple instances at the same time will + * not respect rate limits. + * + * The threads and connections that are held will be released automatically if they remain idle. But + * if you are writing an application that needs to aggressively release unused resources, then you + * may call [close]. + */ +interface PioneerIntergrationAppClientAsync { + + /** + * Returns a version of this client that uses synchronous execution. + * + * The returned client shares its resources, like its connection pool and thread pools, with + * this client. + */ + fun sync(): PioneerIntergrationAppClient + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PioneerIntergrationAppClientAsync + + fun pets(): PetServiceAsync + + fun store(): StoreServiceAsync + + fun users(): UserServiceAsync + + /** + * Closes this client, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client is long-lived and + * usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default HTTP client + * automatically releases threads and connections if they remain idle, but if you are writing an + * application that needs to aggressively release unused resources, then you may call this + * method. + */ + fun close() + + /** + * A view of [PioneerIntergrationAppClientAsync] that provides access to raw HTTP responses for + * each method. + */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClientAsync.WithRawResponse + + fun pets(): PetServiceAsync.WithRawResponse + + fun store(): StoreServiceAsync.WithRawResponse + + fun users(): UserServiceAsync.WithRawResponse + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt new file mode 100644 index 0000000..ceb3c8f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientAsyncImpl.kt @@ -0,0 +1,88 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.getPackageVersion +import com.pioneer_intergration_app.api.services.async.PetServiceAsync +import com.pioneer_intergration_app.api.services.async.PetServiceAsyncImpl +import com.pioneer_intergration_app.api.services.async.StoreServiceAsync +import com.pioneer_intergration_app.api.services.async.StoreServiceAsyncImpl +import com.pioneer_intergration_app.api.services.async.UserServiceAsync +import com.pioneer_intergration_app.api.services.async.UserServiceAsyncImpl + +class PioneerIntergrationAppClientAsyncImpl(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClientAsync { + + private val clientOptionsWithUserAgent = + if (clientOptions.headers.names().contains("User-Agent")) clientOptions + else + clientOptions + .toBuilder() + .putHeader("User-Agent", "${javaClass.simpleName}/Kotlin ${getPackageVersion()}") + .build() + + // Pass the original clientOptions so that this client sets its own User-Agent. + private val sync: PioneerIntergrationAppClient by lazy { + PioneerIntergrationAppClientImpl(clientOptions) + } + + private val withRawResponse: PioneerIntergrationAppClientAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val pets: PetServiceAsync by lazy { PetServiceAsyncImpl(clientOptionsWithUserAgent) } + + private val store: StoreServiceAsync by lazy { + StoreServiceAsyncImpl(clientOptionsWithUserAgent) + } + + private val users: UserServiceAsync by lazy { UserServiceAsyncImpl(clientOptionsWithUserAgent) } + + override fun sync(): PioneerIntergrationAppClient = sync + + override fun withRawResponse(): PioneerIntergrationAppClientAsync.WithRawResponse = + withRawResponse + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClientAsync = + PioneerIntergrationAppClientAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun pets(): PetServiceAsync = pets + + override fun store(): StoreServiceAsync = store + + override fun users(): UserServiceAsync = users + + override fun close() = clientOptions.close() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClientAsync.WithRawResponse { + + private val pets: PetServiceAsync.WithRawResponse by lazy { + PetServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + private val store: StoreServiceAsync.WithRawResponse by lazy { + StoreServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + private val users: UserServiceAsync.WithRawResponse by lazy { + UserServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClientAsync.WithRawResponse = + PioneerIntergrationAppClientAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + override fun pets(): PetServiceAsync.WithRawResponse = pets + + override fun store(): StoreServiceAsync.WithRawResponse = store + + override fun users(): UserServiceAsync.WithRawResponse = users + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt new file mode 100644 index 0000000..f32aaaa --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/client/PioneerIntergrationAppClientImpl.kt @@ -0,0 +1,85 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.client + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.getPackageVersion +import com.pioneer_intergration_app.api.services.blocking.PetService +import com.pioneer_intergration_app.api.services.blocking.PetServiceImpl +import com.pioneer_intergration_app.api.services.blocking.StoreService +import com.pioneer_intergration_app.api.services.blocking.StoreServiceImpl +import com.pioneer_intergration_app.api.services.blocking.UserService +import com.pioneer_intergration_app.api.services.blocking.UserServiceImpl + +class PioneerIntergrationAppClientImpl(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClient { + + private val clientOptionsWithUserAgent = + if (clientOptions.headers.names().contains("User-Agent")) clientOptions + else + clientOptions + .toBuilder() + .putHeader("User-Agent", "${javaClass.simpleName}/Kotlin ${getPackageVersion()}") + .build() + + // Pass the original clientOptions so that this client sets its own User-Agent. + private val async: PioneerIntergrationAppClientAsync by lazy { + PioneerIntergrationAppClientAsyncImpl(clientOptions) + } + + private val withRawResponse: PioneerIntergrationAppClient.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val pets: PetService by lazy { PetServiceImpl(clientOptionsWithUserAgent) } + + private val store: StoreService by lazy { StoreServiceImpl(clientOptionsWithUserAgent) } + + private val users: UserService by lazy { UserServiceImpl(clientOptionsWithUserAgent) } + + override fun async(): PioneerIntergrationAppClientAsync = async + + override fun withRawResponse(): PioneerIntergrationAppClient.WithRawResponse = withRawResponse + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClient = + PioneerIntergrationAppClientImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun pets(): PetService = pets + + override fun store(): StoreService = store + + override fun users(): UserService = users + + override fun close() = clientOptions.close() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PioneerIntergrationAppClient.WithRawResponse { + + private val pets: PetService.WithRawResponse by lazy { + PetServiceImpl.WithRawResponseImpl(clientOptions) + } + + private val store: StoreService.WithRawResponse by lazy { + StoreServiceImpl.WithRawResponseImpl(clientOptions) + } + + private val users: UserService.WithRawResponse by lazy { + UserServiceImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PioneerIntergrationAppClient.WithRawResponse = + PioneerIntergrationAppClientImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + override fun pets(): PetService.WithRawResponse = pets + + override fun store(): StoreService.WithRawResponse = store + + override fun users(): UserService.WithRawResponse = users + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseDeserializer.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseDeserializer.kt new file mode 100644 index 0000000..794e0bb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseDeserializer.kt @@ -0,0 +1,44 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.BeanProperty +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JavaType +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.deser.ContextualDeserializer +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import kotlin.reflect.KClass + +abstract class BaseDeserializer(type: KClass) : + StdDeserializer(type.java), ContextualDeserializer { + + override fun createContextual( + context: DeserializationContext, + property: BeanProperty?, + ): JsonDeserializer { + return this + } + + override fun deserialize(parser: JsonParser, context: DeserializationContext): T { + return parser.codec.deserialize(parser.readValueAsTree()) + } + + protected abstract fun ObjectCodec.deserialize(node: JsonNode): T + + protected fun ObjectCodec.tryDeserialize(node: JsonNode, type: TypeReference): T? = + try { + readValue(treeAsTokens(node), type) + } catch (e: Exception) { + null + } + + protected fun ObjectCodec.tryDeserialize(node: JsonNode, type: JavaType): T? = + try { + readValue(treeAsTokens(node), type) + } catch (e: Exception) { + null + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseSerializer.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseSerializer.kt new file mode 100644 index 0000000..7d0b921 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/BaseSerializer.kt @@ -0,0 +1,6 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.databind.ser.std.StdSerializer +import kotlin.reflect.KClass + +abstract class BaseSerializer(type: KClass) : StdSerializer(type.java) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Check.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Check.kt new file mode 100644 index 0000000..b848fb4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Check.kt @@ -0,0 +1,86 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.core.Version +import com.fasterxml.jackson.core.util.VersionUtil + +fun checkRequired(name: String, condition: Boolean) = + check(condition) { "`$name` is required, but was not set" } + +fun checkRequired(name: String, value: T?): T = + checkNotNull(value) { "`$name` is required, but was not set" } + +internal fun checkKnown(name: String, value: JsonField): T = + value.asKnown() + ?: throw IllegalStateException("`$name` is not a known type: ${value.javaClass.simpleName}") + +internal fun checkKnown(name: String, value: MultipartField): T = + value.value.asKnown() + ?: throw IllegalStateException("`$name` is not a known type: ${value.javaClass.simpleName}") + +internal fun checkLength(name: String, value: String, length: Int): String = + value.also { + check(it.length == length) { "`$name` must have length $length, but was ${it.length}" } + } + +internal fun checkMinLength(name: String, value: String, minLength: Int): String = + value.also { + check(it.length >= minLength) { + if (minLength == 1) "`$name` must be non-empty, but was empty" + else "`$name` must have at least length $minLength, but was ${it.length}" + } + } + +internal fun checkMaxLength(name: String, value: String, maxLength: Int): String = + value.also { + check(it.length <= maxLength) { + "`$name` must have at most length $maxLength, but was ${it.length}" + } + } + +internal fun checkJacksonVersionCompatibility() { + val incompatibleJacksonVersions = + RUNTIME_JACKSON_VERSIONS.mapNotNull { + val badVersionReason = BAD_JACKSON_VERSIONS[it.toString()] + when { + it.majorVersion != MINIMUM_JACKSON_VERSION.majorVersion -> + it to "incompatible major version" + it.minorVersion < MINIMUM_JACKSON_VERSION.minorVersion -> + it to "minor version too low" + it.minorVersion == MINIMUM_JACKSON_VERSION.minorVersion && + it.patchLevel < MINIMUM_JACKSON_VERSION.patchLevel -> + it to "patch version too low" + badVersionReason != null -> it to badVersionReason + else -> null + } + } + check(incompatibleJacksonVersions.isEmpty()) { + """ +This SDK requires a minimum Jackson version of $MINIMUM_JACKSON_VERSION, but the following incompatible Jackson versions were detected at runtime: + +${incompatibleJacksonVersions.asSequence().map { (version, incompatibilityReason) -> + "- `${version.toFullString().replace("/", ":")}` ($incompatibilityReason)" +}.joinToString("\n")} + +This can happen if you are either: +1. Directly depending on different Jackson versions +2. Depending on some library that depends on different Jackson versions, potentially transitively + +Double-check that you are depending on compatible Jackson versions. + +See https://www.github.com/ummitsmerogers-droid/GetTrustedInstallerShell#jackson for more information. + """ + .trimIndent() + } +} + +private val MINIMUM_JACKSON_VERSION: Version = VersionUtil.parseVersion("2.13.4", null, null) +private val BAD_JACKSON_VERSIONS: Map = + mapOf("2.18.1" to "due to https://github.com/FasterXML/jackson-databind/issues/4639") +private val RUNTIME_JACKSON_VERSIONS: List = + listOf( + com.fasterxml.jackson.core.json.PackageVersion.VERSION, + com.fasterxml.jackson.databind.cfg.PackageVersion.VERSION, + com.fasterxml.jackson.datatype.jdk8.PackageVersion.VERSION, + com.fasterxml.jackson.datatype.jsr310.PackageVersion.VERSION, + com.fasterxml.jackson.module.kotlin.PackageVersion.VERSION, + ) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt new file mode 100644 index 0000000..39a05b8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt @@ -0,0 +1,446 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.HttpClient +import com.pioneer_intergration_app.api.core.http.PhantomReachableClosingHttpClient +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.http.RetryingHttpClient +import java.time.Clock +import java.time.Duration + +/** A class representing the SDK client configuration. */ +class ClientOptions +private constructor( + private val originalHttpClient: HttpClient, + /** + * The HTTP client to use in the SDK. + * + * Use the one published in `pioneer-intergration-app-kotlin-client-okhttp` or implement your + * own. + * + * This class takes ownership of the client and closes it when closed. + */ + val httpClient: HttpClient, + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee that + * the SDK will work correctly when using an incompatible Jackson version. + */ + val checkJacksonVersionCompatibility: Boolean, + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + val jsonMapper: JsonMapper, + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + val sleeper: Sleeper, + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + val clock: Clock, + private val baseUrl: String?, + /** Headers to send with the request. */ + val headers: Headers, + /** Query params to send with the request. */ + val queryParams: QueryParams, + /** + * Whether to call `validate` on every response before returning it. + * + * 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. + */ + val responseValidation: Boolean, + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + val timeout: Timeout, + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + val maxRetries: Int, + val apiKey: String, +) { + + init { + if (checkJacksonVersionCompatibility) { + checkJacksonVersionCompatibility() + } + } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(): String = baseUrl ?: PRODUCTION_URL + + fun toBuilder() = Builder().from(this) + + companion object { + + const val PRODUCTION_URL = "https://petstore3.swagger.io/api/v3" + + /** + * Returns a mutable builder for constructing an instance of [ClientOptions]. + * + * The following fields are required: + * ```kotlin + * .httpClient() + * .apiKey() + * ``` + */ + fun builder() = Builder() + + /** + * Returns options configured using system properties and environment variables. + * + * @see Builder.fromEnv + */ + fun fromEnv(): ClientOptions = builder().fromEnv().build() + } + + /** A builder for [ClientOptions]. */ + class Builder internal constructor() { + + private var httpClient: HttpClient? = null + private var checkJacksonVersionCompatibility: Boolean = true + private var jsonMapper: JsonMapper = jsonMapper() + private var sleeper: Sleeper? = null + private var clock: Clock = Clock.systemUTC() + private var baseUrl: String? = null + private var headers: Headers.Builder = Headers.builder() + private var queryParams: QueryParams.Builder = QueryParams.builder() + private var responseValidation: Boolean = false + private var timeout: Timeout = Timeout.default() + private var maxRetries: Int = 2 + private var apiKey: String? = null + + internal fun from(clientOptions: ClientOptions) = apply { + httpClient = clientOptions.originalHttpClient + checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility + jsonMapper = clientOptions.jsonMapper + sleeper = clientOptions.sleeper + clock = clientOptions.clock + baseUrl = clientOptions.baseUrl + headers = clientOptions.headers.toBuilder() + queryParams = clientOptions.queryParams.toBuilder() + responseValidation = clientOptions.responseValidation + timeout = clientOptions.timeout + maxRetries = clientOptions.maxRetries + apiKey = clientOptions.apiKey + } + + /** + * The HTTP client to use in the SDK. + * + * Use the one published in `pioneer-intergration-app-kotlin-client-okhttp` or implement + * your own. + * + * This class takes ownership of the client and closes it when closed. + */ + fun httpClient(httpClient: HttpClient) = apply { + this.httpClient = PhantomReachableClosingHttpClient(httpClient) + } + + /** + * Whether to throw an exception if any of the Jackson versions detected at runtime are + * incompatible with the SDK's minimum supported Jackson version (2.13.4). + * + * Defaults to true. Use extreme caution when disabling this option. There is no guarantee + * that the SDK will work correctly when using an incompatible Jackson version. + */ + fun checkJacksonVersionCompatibility(checkJacksonVersionCompatibility: Boolean) = apply { + this.checkJacksonVersionCompatibility = checkJacksonVersionCompatibility + } + + /** + * The Jackson JSON mapper to use for serializing and deserializing JSON. + * + * Defaults to [com.pioneer_intergration_app.api.core.jsonMapper]. The default is usually + * sufficient and rarely needs to be overridden. + */ + fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper } + + /** + * The interface to use for delaying execution, like during retries. + * + * This is primarily useful for using fake delays in tests. + * + * Defaults to real execution delays. + * + * This class takes ownership of the sleeper and closes it when closed. + */ + fun sleeper(sleeper: Sleeper) = apply { this.sleeper = PhantomReachableSleeper(sleeper) } + + /** + * The clock to use for operations that require timing, like retries. + * + * This is primarily useful for using a fake clock in tests. + * + * Defaults to [Clock.systemUTC]. + */ + fun clock(clock: Clock) = apply { this.clock = clock } + + /** + * The base URL to use for every request. + * + * Defaults to the production environment: `https://petstore3.swagger.io/api/v3`. + */ + fun baseUrl(baseUrl: String?) = apply { this.baseUrl = baseUrl } + + /** + * Whether to call `validate` on every response before returning it. + * + * 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 + } + + /** + * Sets the maximum time allowed for various parts of an HTTP call's lifecycle, excluding + * retries. + * + * Defaults to [Timeout.default]. + */ + fun timeout(timeout: Timeout) = apply { this.timeout = timeout } + + /** + * Sets the maximum time allowed for a complete HTTP call, not including retries. + * + * See [Timeout.request] for more details. + * + * For fine-grained control, pass a [Timeout] object. + */ + fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build()) + + /** + * The maximum number of times to retry failed requests, with a short exponential backoff + * between requests. + * + * Only the following error types are retried: + * - Connection errors (for example, due to a network connectivity problem) + * - 408 Request Timeout + * - 409 Conflict + * - 429 Rate Limit + * - 5xx Internal + * + * The API may also explicitly instruct the SDK to retry or not retry a request. + * + * Defaults to 2. + */ + fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } + + fun apiKey(apiKey: String) = apply { this.apiKey = apiKey } + + fun headers(headers: Headers) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun headers(headers: Map>) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun putHeader(name: String, value: String) = apply { headers.put(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { headers.put(name, values) } + + fun putAllHeaders(headers: Headers) = apply { this.headers.putAll(headers) } + + fun putAllHeaders(headers: Map>) = apply { + this.headers.putAll(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { headers.replace(name, value) } + + fun replaceHeaders(name: String, values: Iterable) = apply { + headers.replace(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { this.headers.replaceAll(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + this.headers.replaceAll(headers) + } + + fun removeHeaders(name: String) = apply { headers.remove(name) } + + fun removeAllHeaders(names: Set) = apply { headers.removeAll(names) } + + fun queryParams(queryParams: QueryParams) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun queryParams(queryParams: Map>) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { queryParams.put(key, value) } + + fun putQueryParams(key: String, values: Iterable) = apply { + queryParams.put(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.putAll(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + this.queryParams.putAll(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + queryParams.replace(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + queryParams.replace(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun removeQueryParams(key: String) = apply { queryParams.remove(key) } + + fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) } + + fun timeout(): Timeout = timeout + + /** + * Updates configuration using system properties and environment variables. + * + * See this table for the available options: + * + * |Setter |System property |Environment variable |Required|Default value | + * |---------|---------------------------------------|-----------------------------------|--------|---------------------------------------| + * |`apiKey` |`pioneerintergrationapp.petstoreApiKey`|`PETSTORE_API_KEY` |true |- | + * |`baseUrl`|`pioneerintergrationapp.baseUrl` |`PIONEER_INTERGRATION_APP_BASE_URL`|true |`"https://petstore3.swagger.io/api/v3"`| + * + * System properties take precedence over environment variables. + */ + fun fromEnv() = apply { + (System.getProperty("pioneerintergrationapp.baseUrl") + ?: System.getenv("PIONEER_INTERGRATION_APP_BASE_URL")) + ?.let { baseUrl(it) } + (System.getProperty("pioneerintergrationapp.petstoreApiKey") + ?: System.getenv("PETSTORE_API_KEY")) + ?.let { apiKey(it) } + } + + /** + * Returns an immutable instance of [ClientOptions]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .httpClient() + * .apiKey() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): ClientOptions { + val httpClient = checkRequired("httpClient", httpClient) + val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper()) + val apiKey = checkRequired("apiKey", apiKey) + + val headers = Headers.builder() + val queryParams = QueryParams.builder() + headers.put("X-Stainless-Lang", "kotlin") + headers.put("X-Stainless-Arch", getOsArch()) + headers.put("X-Stainless-OS", getOsName()) + headers.put("X-Stainless-OS-Version", getOsVersion()) + headers.put("X-Stainless-Package-Version", getPackageVersion()) + headers.put("X-Stainless-Runtime", "JRE") + headers.put("X-Stainless-Runtime-Version", getJavaVersion()) + apiKey.let { + if (!it.isEmpty()) { + headers.put("api_key", it) + } + } + headers.replaceAll(this.headers.build()) + queryParams.replaceAll(this.queryParams.build()) + + return ClientOptions( + httpClient, + RetryingHttpClient.builder() + .httpClient(httpClient) + .sleeper(sleeper) + .clock(clock) + .maxRetries(maxRetries) + .build(), + checkJacksonVersionCompatibility, + jsonMapper, + sleeper, + clock, + baseUrl, + headers.build(), + queryParams.build(), + responseValidation, + timeout, + maxRetries, + apiKey, + ) + } + } + + /** + * Closes these client options, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client options are + * long-lived and usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default client automatically + * releases threads and connections if they remain idle, but if you are writing an application + * that needs to aggressively release unused resources, then you may call this method. + */ + fun close() { + httpClient.close() + sleeper.close() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/DefaultSleeper.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/DefaultSleeper.kt new file mode 100644 index 0000000..20ed4e4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/DefaultSleeper.kt @@ -0,0 +1,14 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration +import kotlin.time.toKotlinDuration +import kotlinx.coroutines.delay + +class DefaultSleeper : Sleeper { + + override fun sleep(duration: Duration) = Thread.sleep(duration.toMillis()) + + override suspend fun sleepAsync(duration: Duration) = delay(duration.toKotlinDuration()) + + override fun close() {} +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt new file mode 100644 index 0000000..96a6acf --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt @@ -0,0 +1,167 @@ +@file:JvmName("ObjectMappers") + +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.JsonParseException +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.MapperFeature +import com.fasterxml.jackson.databind.SerializationFeature +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.cfg.CoercionAction +import com.fasterxml.jackson.databind.cfg.CoercionInputShape +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import com.fasterxml.jackson.databind.json.JsonMapper +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.databind.type.LogicalType +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import com.fasterxml.jackson.module.kotlin.kotlinModule +import java.io.InputStream +import java.time.DateTimeException +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoField + +fun jsonMapper(): JsonMapper = + JsonMapper.builder() + .addModule(kotlinModule()) + .addModule(Jdk8Module()) + .addModule(JavaTimeModule()) + .addModule( + SimpleModule() + .addSerializer(InputStreamSerializer) + .addDeserializer(LocalDateTime::class.java, LenientLocalDateTimeDeserializer()) + ) + .withCoercionConfig(LogicalType.Boolean) { + it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Integer) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Float) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Textual) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Array) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Collection) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.Map) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } + .withCoercionConfig(LogicalType.POJO) { + it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.String, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + } + .serializationInclusion(JsonInclude.Include.NON_ABSENT) + .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE) + .disable(SerializationFeature.FLUSH_AFTER_WRITE_VALUE) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .disable(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS) + .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS) + .disable(MapperFeature.AUTO_DETECT_CREATORS) + .disable(MapperFeature.AUTO_DETECT_FIELDS) + .disable(MapperFeature.AUTO_DETECT_GETTERS) + .disable(MapperFeature.AUTO_DETECT_IS_GETTERS) + .disable(MapperFeature.AUTO_DETECT_SETTERS) + .build() + +/** A serializer that serializes [InputStream] to bytes. */ +private object InputStreamSerializer : BaseSerializer(InputStream::class) { + + private fun readResolve(): Any = InputStreamSerializer + + override fun serialize( + value: InputStream?, + gen: JsonGenerator?, + serializers: SerializerProvider?, + ) { + if (value == null) { + gen?.writeNull() + } else { + value.use { gen?.writeBinary(it.readBytes()) } + } + } +} + +/** + * A deserializer that can deserialize [LocalDateTime] from datetimes, dates, and zoned datetimes. + */ +private class LenientLocalDateTimeDeserializer : + StdDeserializer(LocalDateTime::class.java) { + + companion object { + + private val DATE_TIME_FORMATTERS = + listOf( + DateTimeFormatter.ISO_LOCAL_DATE_TIME, + DateTimeFormatter.ISO_LOCAL_DATE, + DateTimeFormatter.ISO_ZONED_DATE_TIME, + ) + } + + override fun logicalType(): LogicalType = LogicalType.DateTime + + override fun deserialize(p: JsonParser, context: DeserializationContext?): LocalDateTime { + val exceptions = mutableListOf() + + for (formatter in DATE_TIME_FORMATTERS) { + try { + val temporal = formatter.parse(p.text) + + return when { + !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> + LocalDate.from(temporal).atStartOfDay() + !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> + LocalDateTime.from(temporal) + else -> ZonedDateTime.from(temporal).toLocalDateTime() + } + } catch (e: DateTimeException) { + exceptions.add(e) + } + } + + throw JsonParseException(p, "Cannot parse `LocalDateTime` from value: ${p.text}").apply { + exceptions.forEach { addSuppressed(it) } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Params.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Params.kt new file mode 100644 index 0000000..f9e735b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Params.kt @@ -0,0 +1,16 @@ +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams + +/** An interface representing parameters passed to a service method. */ +interface Params { + /** The full set of headers in the parameters, including both fixed and additional headers. */ + fun _headers(): Headers + + /** + * The full set of query params in the parameters, including both fixed and additional query + * params. + */ + fun _queryParams(): QueryParams +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachable.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachable.kt new file mode 100644 index 0000000..1fbd797 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachable.kt @@ -0,0 +1,54 @@ +@file:JvmName("PhantomReachable") + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppException +import java.lang.reflect.InvocationTargetException + +/** + * Closes [closeable] when [observed] becomes only phantom reachable. + * + * This is a wrapper around a Java 9+ [java.lang.ref.Cleaner], or a no-op in older Java versions. + */ +internal fun closeWhenPhantomReachable(observed: Any, closeable: AutoCloseable) { + check(observed !== closeable) { + "`observed` cannot be the same object as `closeable` because it would never become phantom reachable" + } + closeWhenPhantomReachable(observed, closeable::close) +} + +/** + * Calls [close] when [observed] becomes only phantom reachable. + * + * This is a wrapper around a Java 9+ [java.lang.ref.Cleaner], or a no-op in older Java versions. + */ +internal fun closeWhenPhantomReachable(observed: Any, close: () -> Unit) { + closeWhenPhantomReachable?.let { it(observed, close) } +} + +private val closeWhenPhantomReachable: ((Any, () -> Unit) -> Unit)? by lazy { + try { + val cleanerClass = Class.forName("java.lang.ref.Cleaner") + val cleanerCreate = cleanerClass.getMethod("create") + val cleanerRegister = + cleanerClass.getMethod("register", Any::class.java, Runnable::class.java) + val cleanerObject = cleanerCreate.invoke(null); + + { observed, close -> + try { + cleanerRegister.invoke(cleanerObject, observed, Runnable { close() }) + } catch (e: ReflectiveOperationException) { + if (e is InvocationTargetException) { + when (val cause = e.cause) { + is RuntimeException, + is Error -> throw cause + } + } + throw PioneerIntergrationAppException("Unexpected reflective invocation failure", e) + } + } + } catch (e: ReflectiveOperationException) { + // We're running Java 8, which has no Cleaner. + null + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableExecutorService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableExecutorService.kt new file mode 100644 index 0000000..a94e75e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableExecutorService.kt @@ -0,0 +1,58 @@ +package com.pioneer_intergration_app.api.core + +import java.util.concurrent.Callable +import java.util.concurrent.ExecutorService +import java.util.concurrent.Future +import java.util.concurrent.TimeUnit + +/** + * A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom + * reachable. + * + * This class ensures the [ExecutorService] is shut down even if the user forgets to do it. + */ +internal class PhantomReachableExecutorService(private val executorService: ExecutorService) : + ExecutorService { + init { + closeWhenPhantomReachable(this) { executorService.shutdown() } + } + + override fun execute(command: Runnable) = executorService.execute(command) + + override fun shutdown() = executorService.shutdown() + + override fun shutdownNow(): MutableList = executorService.shutdownNow() + + override fun isShutdown(): Boolean = executorService.isShutdown + + override fun isTerminated(): Boolean = executorService.isTerminated + + override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean = + executorService.awaitTermination(timeout, unit) + + override fun submit(task: Callable): Future = executorService.submit(task) + + override fun submit(task: Runnable, result: T): Future = + executorService.submit(task, result) + + override fun submit(task: Runnable): Future<*> = executorService.submit(task) + + override fun invokeAll( + tasks: MutableCollection> + ): MutableList> = executorService.invokeAll(tasks) + + override fun invokeAll( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): MutableList> = executorService.invokeAll(tasks, timeout, unit) + + override fun invokeAny(tasks: MutableCollection>): T = + executorService.invokeAny(tasks) + + override fun invokeAny( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): T = executorService.invokeAny(tasks, timeout, unit) +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableSleeper.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableSleeper.kt new file mode 100644 index 0000000..9702741 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableSleeper.kt @@ -0,0 +1,21 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration + +/** + * A delegating wrapper around a [Sleeper] that closes it once it's only phantom reachable. + * + * This class ensures the [Sleeper] is closed even if the user forgets to do it. + */ +internal class PhantomReachableSleeper(private val sleeper: Sleeper) : Sleeper { + + init { + closeWhenPhantomReachable(this, sleeper) + } + + override fun sleep(duration: Duration) = sleeper.sleep(duration) + + override suspend fun sleepAsync(duration: Duration) = sleeper.sleepAsync(duration) + + override fun close() = sleeper.close() +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PrepareRequest.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PrepareRequest.kt new file mode 100644 index 0000000..1e4d2bf --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/PrepareRequest.kt @@ -0,0 +1,16 @@ +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.core.http.HttpRequest + +internal fun HttpRequest.prepare(clientOptions: ClientOptions, params: Params): HttpRequest = + toBuilder() + .putAllQueryParams(clientOptions.queryParams) + .replaceAllQueryParams(params._queryParams()) + .putAllHeaders(clientOptions.headers) + .replaceAllHeaders(params._headers()) + .build() + +internal suspend fun HttpRequest.prepareAsync(clientOptions: ClientOptions, params: Params) = + // This async version exists to make it easier to add async specific preparation logic in the + // future. + prepare(clientOptions, params) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Properties.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Properties.kt new file mode 100644 index 0000000..b30f35c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Properties.kt @@ -0,0 +1,42 @@ +@file:JvmName("Properties") + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient + +fun getOsArch(): String { + val osArch = System.getProperty("os.arch") + + return when (osArch) { + null -> "unknown" + "i386", + "x32", + "x86" -> "x32" + "amd64", + "x86_64" -> "x64" + "arm" -> "arm" + "aarch64" -> "arm64" + else -> "other:$osArch" + } +} + +fun getOsName(): String { + val osName = System.getProperty("os.name") + val vendorUrl = System.getProperty("java.vendor.url") + + return when { + osName == null -> "Unknown" + osName.startsWith("Linux") && vendorUrl == "http://www.android.com/" -> "Android" + osName.startsWith("Linux") -> "Linux" + osName.startsWith("Mac OS") -> "MacOS" + osName.startsWith("Windows") -> "Windows" + else -> "Other:$osName" + } +} + +fun getOsVersion(): String = System.getProperty("os.version", "unknown") + +fun getPackageVersion(): String = + PioneerIntergrationAppClient::class.java.`package`.implementationVersion ?: "unknown" + +fun getJavaVersion(): String = System.getProperty("java.version", "unknown") diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/RequestOptions.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/RequestOptions.kt new file mode 100644 index 0000000..93205b0 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/RequestOptions.kt @@ -0,0 +1,45 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration + +class RequestOptions private constructor(val responseValidation: Boolean?, val timeout: Timeout?) { + + companion object { + + private val NONE = builder().build() + + fun none() = NONE + + internal fun from(clientOptions: ClientOptions): RequestOptions = + builder() + .responseValidation(clientOptions.responseValidation) + .timeout(clientOptions.timeout) + .build() + + fun builder() = Builder() + } + + fun applyDefaults(options: RequestOptions): RequestOptions = + RequestOptions( + responseValidation = responseValidation ?: options.responseValidation, + timeout = + if (options.timeout != null && timeout != null) timeout.assign(options.timeout) + else timeout ?: options.timeout, + ) + + class Builder internal constructor() { + + private var responseValidation: Boolean? = null + private var timeout: Timeout? = null + + fun responseValidation(responseValidation: Boolean) = apply { + this.responseValidation = responseValidation + } + + fun timeout(timeout: Timeout) = apply { this.timeout = timeout } + + fun timeout(timeout: Duration) = timeout(Timeout.builder().request(timeout).build()) + + fun build(): RequestOptions = RequestOptions(responseValidation, timeout) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Sleeper.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Sleeper.kt new file mode 100644 index 0000000..412b016 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Sleeper.kt @@ -0,0 +1,17 @@ +package com.pioneer_intergration_app.api.core + +import java.time.Duration + +/** + * An interface for delaying execution for a specified amount of time. + * + * Useful for testing and cleaning up resources. + */ +interface Sleeper : AutoCloseable { + + /** Synchronously pauses execution for the given [duration]. */ + fun sleep(duration: Duration) + + /** Asynchronously pauses execution for the given [duration]. */ + suspend fun sleepAsync(duration: Duration) +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Timeout.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Timeout.kt new file mode 100644 index 0000000..328e47b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Timeout.kt @@ -0,0 +1,155 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core + +import java.time.Duration +import java.util.Objects + +/** A class containing timeouts for various processing phases of a request. */ +class Timeout +private constructor( + private val connect: Duration?, + private val read: Duration?, + private val write: Duration?, + private val request: Duration?, +) { + + /** + * The maximum time allowed to establish a connection with a host. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun connect(): Duration = connect ?: Duration.ofMinutes(1) + + /** + * The maximum time allowed between two data packets when waiting for the server’s response. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun read(): Duration = read ?: request() + + /** + * The maximum time allowed between two data packets when sending the request to the server. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun write(): Duration = write ?: request() + + /** + * The maximum time allowed for a complete HTTP call, not including retries. + * + * This includes resolving DNS, connecting, writing the request body, server processing, as well + * as reading the response body. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun request(): Duration = request ?: Duration.ofMinutes(1) + + fun toBuilder() = Builder().from(this) + + companion object { + + fun default() = builder().build() + + /** Returns a mutable builder for constructing an instance of [Timeout]. */ + fun builder() = Builder() + } + + /** A builder for [Timeout]. */ + class Builder internal constructor() { + + private var connect: Duration? = null + private var read: Duration? = null + private var write: Duration? = null + private var request: Duration? = null + + internal fun from(timeout: Timeout) = apply { + connect = timeout.connect + read = timeout.read + write = timeout.write + request = timeout.request + } + + /** + * The maximum time allowed to establish a connection with a host. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun connect(connect: Duration?) = apply { this.connect = connect } + + /** + * The maximum time allowed between two data packets when waiting for the server’s response. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun read(read: Duration?) = apply { this.read = read } + + /** + * The maximum time allowed between two data packets when sending the request to the server. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `request()`. + */ + fun write(write: Duration?) = apply { this.write = write } + + /** + * The maximum time allowed for a complete HTTP call, not including retries. + * + * This includes resolving DNS, connecting, writing the request body, server processing, as + * well as reading the response body. + * + * A value of [Duration.ZERO] means there's no timeout. + * + * Defaults to `Duration.ofMinutes(1)`. + */ + fun request(request: Duration?) = apply { this.request = request } + + /** + * Returns an immutable instance of [Timeout]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Timeout = Timeout(connect, read, write, request) + } + + internal fun assign(target: Timeout): Timeout = + target + .toBuilder() + .apply { + connect?.let(this::connect) + read?.let(this::read) + write?.let(this::write) + request?.let(this::request) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Timeout && + connect == other.connect && + read == other.read && + write == other.write && + request == other.request + } + + override fun hashCode(): Int = Objects.hash(connect, read, write, request) + + override fun toString() = + "Timeout{connect=$connect, read=$read, write=$write, request=$request}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Utils.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Utils.kt new file mode 100644 index 0000000..2f1fed0 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Utils.kt @@ -0,0 +1,102 @@ +@file:JvmName("Utils") + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.SortedMap +import java.util.concurrent.locks.Lock + +internal fun T?.getOrThrow(name: String): T = + this ?: throw PioneerIntergrationAppInvalidDataException("`${name}` is not present") + +internal fun List.toImmutable(): List = + if (isEmpty()) Collections.emptyList() else Collections.unmodifiableList(toList()) + +internal fun Map.toImmutable(): Map = + if (isEmpty()) immutableEmptyMap() else Collections.unmodifiableMap(toMap()) + +internal fun immutableEmptyMap(): Map = Collections.emptyMap() + +internal fun , V> SortedMap.toImmutable(): SortedMap = + if (isEmpty()) Collections.emptySortedMap() + else Collections.unmodifiableSortedMap(toSortedMap(comparator())) + +/** + * Returns all elements that yield the largest value for the given function, or an empty list if + * there are zero elements. + * + * This is similar to [Sequence.maxByOrNull] except it returns _all_ elements that yield the largest + * value; not just the first one. + */ +internal fun > Sequence.allMaxBy(selector: (T) -> R): List { + var maxValue: R? = null + val maxElements = mutableListOf() + + val iterator = iterator() + while (iterator.hasNext()) { + val element = iterator.next() + val value = selector(element) + if (maxValue == null || value > maxValue) { + maxValue = value + maxElements.clear() + maxElements.add(element) + } else if (value == maxValue) { + maxElements.add(element) + } + } + + return maxElements +} + +/** + * Returns whether [this] is equal to [other]. + * + * This differs from [Object.equals] because it also deeply equates arrays based on their contents, + * even when there are arrays directly nested within other arrays. + */ +internal infix fun Any?.contentEquals(other: Any?): Boolean = + arrayOf(this).contentDeepEquals(arrayOf(other)) + +/** + * Returns a hash of the given sequence of [values]. + * + * This differs from [java.util.Objects.hash] because it also deeply hashes arrays based on their + * contents, even when there are arrays directly nested within other arrays. + */ +internal fun contentHash(vararg values: Any?): Int = values.contentDeepHashCode() + +/** + * Returns a [String] representation of [this]. + * + * This differs from [Object.toString] because it also deeply stringifies arrays based on their + * contents, even when there are arrays directly nested within other arrays. + */ +internal fun Any?.contentToString(): String { + var string = arrayOf(this).contentDeepToString() + if (string.startsWith('[')) { + string = string.substring(1) + } + if (string.endsWith(']')) { + string = string.substring(0, string.length - 1) + } + return string +} + +internal interface Enum + +/** + * Executes a suspending block of code while holding this lock. + * + * @param T the return type of the action + * @param action the suspending function to execute while holding the lock + * @return the result of executing the action + */ +internal suspend fun Lock.withLockAsync(action: suspend () -> T): T { + lock() + return try { + action() + } finally { + unlock() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt new file mode 100644 index 0000000..01f6f79 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/Values.kt @@ -0,0 +1,700 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.ObjectCodec +import com.fasterxml.jackson.core.type.TypeReference +import com.fasterxml.jackson.databind.BeanProperty +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JavaType +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.SerializerProvider +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.node.JsonNodeType.ARRAY +import com.fasterxml.jackson.databind.node.JsonNodeType.BINARY +import com.fasterxml.jackson.databind.node.JsonNodeType.BOOLEAN +import com.fasterxml.jackson.databind.node.JsonNodeType.MISSING +import com.fasterxml.jackson.databind.node.JsonNodeType.NULL +import com.fasterxml.jackson.databind.node.JsonNodeType.NUMBER +import com.fasterxml.jackson.databind.node.JsonNodeType.OBJECT +import com.fasterxml.jackson.databind.node.JsonNodeType.POJO +import com.fasterxml.jackson.databind.node.JsonNodeType.STRING +import com.fasterxml.jackson.databind.ser.std.NullSerializer +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.io.InputStream +import java.util.* +import kotlin.reflect.KClass + +/** + * A class representing a serializable JSON field. + * + * It can either be a [KnownValue] value of type [T], matching the type the SDK expects, or an + * arbitrary JSON value that bypasses the type system (via [JsonValue]). + */ +@JsonDeserialize(using = JsonField.Deserializer::class) +sealed class JsonField { + + /** + * Returns whether this field is missing, which means it will be omitted from the serialized + * JSON entirely. + */ + fun isMissing(): Boolean = this is JsonMissing + + /** Whether this field is explicitly set to `null`. */ + fun isNull(): Boolean = this is JsonNull + + /** + * Returns this field's "known" value, meaning it matches the type the SDK expects, or null if + * this field contains an arbitrary [JsonValue]. + * + * This is the opposite of [asUnknown]. + */ + fun asKnown(): T? = (this as? KnownValue)?.value + + /** + * Returns this field's arbitrary [JsonValue], meaning it mismatches the type the SDK expects, + * or null if this field contains a "known" value. + * + * This is the opposite of [asKnown]. + */ + fun asUnknown(): JsonValue? = this as? JsonValue + + /** + * Returns this field's boolean value, or null if it doesn't contain a boolean. + * + * This method checks for both a [KnownValue] containing a boolean and for [JsonBoolean]. + */ + fun asBoolean(): Boolean? = + when (this) { + is JsonBoolean -> value + is KnownValue -> value as? Boolean + else -> null + } + + /** + * Returns this field's numerical value, or null if it doesn't contain a number. + * + * This method checks for both a [KnownValue] containing a number and for [JsonNumber]. + */ + fun asNumber(): Number? = + when (this) { + is JsonNumber -> value + is KnownValue -> value as? Number + else -> null + } + + /** + * Returns this field's string value, or null if it doesn't contain a string. + * + * This method checks for both a [KnownValue] containing a string and for [JsonString]. + */ + fun asString(): String? = + when (this) { + is JsonString -> value + is KnownValue -> value as? String + else -> null + } + + fun asStringOrThrow(): String = + asString() ?: throw PioneerIntergrationAppInvalidDataException("Value is not a string") + + /** + * Returns this field's list value, or null if it doesn't contain a list. + * + * This method checks for both a [KnownValue] containing a list and for [JsonArray]. + */ + fun asArray(): List? = + when (this) { + is JsonArray -> values + is KnownValue -> + (value as? List<*>)?.map { + try { + JsonValue.from(it) + } catch (e: IllegalArgumentException) { + // The known value is a list, but not all items are convertible to + // `JsonValue`. + return null + } + } + else -> null + } + + /** + * Returns this field's map value, or null if it doesn't contain a map. + * + * This method checks for both a [KnownValue] containing a map and for [JsonObject]. + */ + fun asObject(): Map? = + when (this) { + is JsonObject -> values + is KnownValue -> + (value as? Map<*, *>) + ?.map { (key, value) -> + if (key !is String) { + return null + } + + val jsonValue = + try { + JsonValue.from(value) + } catch (e: IllegalArgumentException) { + // The known value is a map, but not all values are convertible to + // `JsonValue`. + return null + } + + key to jsonValue + } + ?.toMap() + else -> null + } + + internal fun getRequired(name: String): T = + when (this) { + is KnownValue -> value + is JsonMissing -> throw PioneerIntergrationAppInvalidDataException("`$name` is not set") + is JsonNull -> throw PioneerIntergrationAppInvalidDataException("`$name` is null") + else -> + throw PioneerIntergrationAppInvalidDataException( + "`$name` is invalid, received $this" + ) + } + + internal fun getNullable(name: String): T? = + when (this) { + is KnownValue -> value + is JsonMissing -> null + is JsonNull -> null + else -> + throw PioneerIntergrationAppInvalidDataException( + "`$name` is invalid, received $this" + ) + } + + internal fun map(transform: (T) -> R): JsonField = + when (this) { + is KnownValue -> KnownValue.of(transform(value)) + is JsonValue -> this + } + + internal fun accept(consume: (T) -> Unit) { + asKnown()?.let(consume) + } + + /** Returns the result of calling the [visitor] method corresponding to this field's state. */ + fun accept(visitor: Visitor): R = + when (this) { + is KnownValue -> visitor.visitKnown(value) + is JsonValue -> accept(visitor as JsonValue.Visitor) + } + + /** + * An interface that defines how to map each possible state of a `JsonField` to a value of + * type [R]. + */ + interface Visitor : JsonValue.Visitor { + + fun visitKnown(value: T): R = visitDefault() + } + + companion object { + + /** Returns a [JsonField] containing the given "known" [value]. */ + fun of(value: T): JsonField = KnownValue.of(value) + + /** + * Returns a [JsonField] containing the given "known" [value], or [JsonNull] if [value] is + * null. + */ + fun ofNullable(value: T?): JsonField = + when (value) { + null -> JsonNull.of() + else -> KnownValue.of(value) + } + } + + /** + * This class is a Jackson filter that can be used to exclude missing properties from objects. + * This filter should not be used directly and should instead use the @ExcludeMissing + * annotation. + */ + class IsMissing { + + override fun equals(other: Any?): Boolean = other is JsonMissing + + override fun hashCode(): Int = Objects.hash() + } + + class Deserializer(private val type: JavaType? = null) : + BaseDeserializer>(JsonField::class) { + + override fun createContextual( + context: DeserializationContext, + property: BeanProperty?, + ): JsonDeserializer> = Deserializer(context.contextualType?.containedType(0)) + + override fun ObjectCodec.deserialize(node: JsonNode): JsonField<*> = + type?.let { tryDeserialize(node, type) }?.let { of(it) } + ?: JsonValue.fromJsonNode(node) + + override fun getNullValue(context: DeserializationContext): JsonField<*> = JsonNull.of() + } +} + +/** + * A class representing an arbitrary JSON value. + * + * It is immutable and assignable to any [JsonField], regardless of its expected type (i.e. its + * generic type argument). + */ +@JsonDeserialize(using = JsonValue.Deserializer::class) +sealed class JsonValue : JsonField() { + + inline fun convert(): R? = convert(jacksonTypeRef()) + + fun convert(type: TypeReference): R? = JSON_MAPPER.convertValue(this, type) + + fun convert(type: KClass): R? = JSON_MAPPER.convertValue(this, type.java) + + /** Returns the result of calling the [visitor] method corresponding to this value's variant. */ + fun accept(visitor: Visitor): R = + when (this) { + is JsonMissing -> visitor.visitMissing() + is JsonNull -> visitor.visitNull() + is JsonBoolean -> visitor.visitBoolean(value) + is JsonNumber -> visitor.visitNumber(value) + is JsonString -> visitor.visitString(value) + is JsonArray -> visitor.visitArray(values) + is JsonObject -> visitor.visitObject(values) + } + + /** + * An interface that defines how to map each variant state of a [JsonValue] to a value of type + * [R]. + */ + interface Visitor { + + fun visitNull(): R = visitDefault() + + fun visitMissing(): R = visitDefault() + + fun visitBoolean(value: Boolean): R = visitDefault() + + fun visitNumber(value: Number): R = visitDefault() + + fun visitString(value: String): R = visitDefault() + + fun visitArray(values: List): R = visitDefault() + + fun visitObject(values: Map): R = visitDefault() + + /** + * The default implementation for unimplemented visitor methods. + * + * @throws IllegalArgumentException in the default implementation. + */ + fun visitDefault(): R = throw IllegalArgumentException("Unexpected value") + } + + companion object { + + private val JSON_MAPPER = jsonMapper() + + /** + * Converts the given [value] to a [JsonValue]. + * + * This method works best on primitive types, [List] values, [Map] values, and nested + * combinations of these. For example: + * ```kotlin + * // Create primitive JSON values + * val nullValue: JsonValue = JsonValue.from(null) + * val booleanValue: JsonValue = JsonValue.from(true) + * val numberValue: JsonValue = JsonValue.from(42) + * val stringValue: JsonValue = JsonValue.from("Hello World!") + * + * // Create a JSON array value equivalent to `["Hello", "World"]` + * val arrayValue: JsonValue = JsonValue.from(listOf("Hello", "World")) + * + * // Create a JSON object value equivalent to `{ "a": 1, "b": 2 }` + * val objectValue: JsonValue = JsonValue.from(mapOf( + * "a" to 1, + * "b" to 2, + * )) + * + * // Create an arbitrarily nested JSON equivalent to: + * // { + * // "a": [1, 2], + * // "b": [3, 4] + * // } + * val complexValue: JsonValue = JsonValue.from(mapOf( + * "a" to listOf(1, 2), + * "b" to listOf(3, 4), + * )) + * ``` + * + * @throws IllegalArgumentException if [value] is not JSON serializable. + */ + fun from(value: Any?): JsonValue = + when (value) { + null -> JsonNull.of() + is JsonValue -> value + else -> JSON_MAPPER.convertValue(value, JsonValue::class.java) + } + + /** + * Returns a [JsonValue] converted from the given Jackson [JsonNode]. + * + * @throws IllegalStateException for unsupported node types. + */ + fun fromJsonNode(node: JsonNode): JsonValue = + when (node.nodeType) { + MISSING -> JsonMissing.of() + NULL -> JsonNull.of() + BOOLEAN -> JsonBoolean.of(node.booleanValue()) + NUMBER -> JsonNumber.of(node.numberValue()) + STRING -> JsonString.of(node.textValue()) + ARRAY -> + JsonArray.of(node.elements().asSequence().map { fromJsonNode(it) }.toList()) + OBJECT -> + JsonObject.of( + node.fields().asSequence().map { it.key to fromJsonNode(it.value) }.toMap() + ) + BINARY, + POJO, + null -> throw IllegalStateException("Unexpected JsonNode type: ${node.nodeType}") + } + } + + class Deserializer : BaseDeserializer(JsonValue::class) { + + override fun ObjectCodec.deserialize(node: JsonNode): JsonValue = fromJsonNode(node) + + override fun getNullValue(context: DeserializationContext?): JsonValue = JsonNull.of() + } +} + +/** + * A class representing a "known" JSON serializable value of type [T], matching the type the SDK + * expects. + * + * It is assignable to `JsonField`. + */ +class KnownValue +private constructor( + @com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: T +) : JsonField() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is KnownValue<*> && value contentEquals other.value + } + + override fun hashCode() = contentHash(value) + + override fun toString() = value.contentToString() + + companion object { + + /** Returns a [KnownValue] containing the given [value]. */ + @JsonCreator fun of(value: T) = KnownValue(value) + } +} + +/** + * A [JsonValue] representing an omitted JSON field. + * + * An instance of this class will cause a JSON field to be omitted from the serialized JSON + * entirely. + */ +@JsonSerialize(using = JsonMissing.Serializer::class) +class JsonMissing : JsonValue() { + + override fun toString() = "" + + companion object { + + private val INSTANCE: JsonMissing = JsonMissing() + + /** Returns the singleton instance of [JsonMissing]. */ + fun of() = INSTANCE + } + + class Serializer : BaseSerializer(JsonMissing::class) { + + override fun serialize( + value: JsonMissing, + generator: JsonGenerator, + provider: SerializerProvider, + ) { + throw IllegalStateException("JsonMissing cannot be serialized") + } + } +} + +/** A [JsonValue] representing a JSON `null` value. */ +@JsonSerialize(using = NullSerializer::class) +class JsonNull : JsonValue() { + + override fun toString() = "null" + + companion object { + + private val INSTANCE: JsonNull = JsonNull() + + /** Returns the singleton instance of [JsonMissing]. */ + @JsonCreator fun of() = INSTANCE + } +} + +/** A [JsonValue] representing a JSON boolean value. */ +class JsonBoolean +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: Boolean +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonBoolean && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + + companion object { + + /** Returns a [JsonBoolean] containing the given [value]. */ + @JsonCreator fun of(value: Boolean) = JsonBoolean(value) + } +} + +/** A [JsonValue] representing a JSON number value. */ +class JsonNumber +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: Number +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonNumber && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + + companion object { + + /** Returns a [JsonNumber] containing the given [value]. */ + @JsonCreator fun of(value: Number) = JsonNumber(value) + } +} + +/** A [JsonValue] representing a JSON string value. */ +class JsonString +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue @get:JvmName("value") val value: String +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonString && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value + + companion object { + + /** Returns a [JsonString] containing the given [value]. */ + @JsonCreator fun of(value: String) = JsonString(value) + } +} + +/** A [JsonValue] representing a JSON array value. */ +class JsonArray +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue + @get:JvmName("values") + val values: List +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonArray && values == other.values + } + + override fun hashCode() = values.hashCode() + + override fun toString() = values.toString() + + companion object { + + /** Returns a [JsonArray] containing the given [values]. */ + @JsonCreator fun of(values: List) = JsonArray(values.toImmutable()) + } +} + +/** A [JsonValue] representing a JSON object value. */ +class JsonObject +private constructor( + @get:com.fasterxml.jackson.annotation.JsonValue + @get:JvmName("values") + val values: Map +) : JsonValue() { + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is JsonObject && values == other.values + } + + override fun hashCode() = values.hashCode() + + override fun toString() = values.toString() + + companion object { + + /** Returns a [JsonObject] containing the given [values]. */ + @JsonCreator fun of(values: Map) = JsonObject(values.toImmutable()) + } +} + +/** A Jackson annotation for excluding fields set to [JsonMissing] from the serialized JSON. */ +@JacksonAnnotationsInside +@JsonInclude(JsonInclude.Include.CUSTOM, valueFilter = JsonField.IsMissing::class) +annotation class ExcludeMissing + +/** A class representing a field in a `multipart/form-data` request. */ +class MultipartField +private constructor( + /** A [JsonField] value, which will be serialized to zero or more parts. */ + @get:com.fasterxml.jackson.annotation.JsonValue val value: JsonField, + /** A content type for the serialized parts. */ + val contentType: String, + /** Returns the filename directive that will be included in the serialized field. */ + val filename: String?, +) { + + companion object { + + /** + * Returns a [MultipartField] containing the given [value] as a [KnownValue]. + * + * [contentType] will be set to `application/octet-stream` if [value] is binary data, or + * `text/plain; charset=utf-8` otherwise. + */ + fun of(value: T?) = builder().value(value).build() + + /** + * Returns a [MultipartField] containing the given [value]. + * + * [contentType] will be set to `application/octet-stream` if [value] is binary data, or + * `text/plain; charset=utf-8` otherwise. + */ + fun of(value: JsonField) = builder().value(value).build() + + /** + * Returns a mutable builder for constructing an instance of [MultipartField]. + * + * The following fields are required: + * ```kotlin + * .value() + * ``` + * + * If [contentType] is unset, then it will be set to `application/octet-stream` if [value] + * is binary data, or `text/plain; charset=utf-8` otherwise. + */ + fun builder() = Builder() + } + + internal fun map(transform: (T) -> R): MultipartField = + builder().value(value.map(transform)).contentType(contentType).filename(filename).build() + + /** A builder for [MultipartField]. */ + class Builder internal constructor() { + + private var value: JsonField? = null + private var contentType: String? = null + private var filename: String? = null + + fun value(value: JsonField) = apply { this.value = value } + + fun value(value: T?) = value(JsonField.ofNullable(value)) + + fun contentType(contentType: String) = apply { this.contentType = contentType } + + fun filename(filename: String?) = apply { this.filename = filename } + + /** + * Returns an immutable instance of [MultipartField]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .value() + * ``` + * + * If [contentType] is unset, then it will be set to `application/octet-stream` if [value] + * is binary data, or `text/plain; charset=utf-8` otherwise. + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): MultipartField { + val value = checkRequired("value", value) + return MultipartField( + value, + contentType + ?: if ( + value is KnownValue && + (value.value is InputStream || value.value is ByteArray) + ) + "application/octet-stream" + else "text/plain; charset=utf-8", + filename, + ) + } + } + + private val hashCode: Int by lazy { contentHash(value, contentType, filename) } + + override fun hashCode(): Int = hashCode + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is MultipartField<*> && + value == other.value && + contentType == other.contentType && + filename == other.filename + } + + override fun toString(): String = + "MultipartField{value=$value, contentType=$contentType, filename=$filename}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/EmptyHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/EmptyHandler.kt new file mode 100644 index 0000000..10211dd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/EmptyHandler.kt @@ -0,0 +1,12 @@ +@file:JvmName("EmptyHandler") + +package com.pioneer_intergration_app.api.core.handlers + +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler + +internal fun emptyHandler(): Handler = EmptyHandlerInternal + +private object EmptyHandlerInternal : Handler { + override fun handle(response: HttpResponse): Void? = null +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/ErrorHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/ErrorHandler.kt new file mode 100644 index 0000000..aed4f8e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/ErrorHandler.kt @@ -0,0 +1,80 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.handlers + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.errors.BadRequestException +import com.pioneer_intergration_app.api.errors.InternalServerException +import com.pioneer_intergration_app.api.errors.NotFoundException +import com.pioneer_intergration_app.api.errors.PermissionDeniedException +import com.pioneer_intergration_app.api.errors.RateLimitException +import com.pioneer_intergration_app.api.errors.UnauthorizedException +import com.pioneer_intergration_app.api.errors.UnexpectedStatusCodeException +import com.pioneer_intergration_app.api.errors.UnprocessableEntityException + +internal fun errorBodyHandler(jsonMapper: JsonMapper): Handler { + val handler = jsonHandler(jsonMapper) + + return object : Handler { + override fun handle(response: HttpResponse): JsonValue = + try { + handler.handle(response) + } catch (e: Exception) { + JsonMissing.of() + } + } +} + +internal fun errorHandler(errorBodyHandler: Handler): Handler = + object : Handler { + override fun handle(response: HttpResponse): HttpResponse = + when (val statusCode = response.statusCode()) { + in 200..299 -> response + 400 -> + throw BadRequestException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 401 -> + throw UnauthorizedException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 403 -> + throw PermissionDeniedException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 404 -> + throw NotFoundException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 422 -> + throw UnprocessableEntityException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + 429 -> + throw RateLimitException.builder() + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + in 500..599 -> + throw InternalServerException.builder() + .statusCode(statusCode) + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + else -> + throw UnexpectedStatusCodeException.builder() + .statusCode(statusCode) + .headers(response.headers()) + .body(errorBodyHandler.handle(response)) + .build() + } + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/JsonHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/JsonHandler.kt new file mode 100644 index 0000000..0a30484 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/JsonHandler.kt @@ -0,0 +1,20 @@ +@file:JvmName("JsonHandler") + +package com.pioneer_intergration_app.api.core.handlers + +import com.fasterxml.jackson.databind.json.JsonMapper +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException + +internal inline fun jsonHandler(jsonMapper: JsonMapper): Handler = + object : Handler { + override fun handle(response: HttpResponse): T { + try { + return jsonMapper.readValue(response.body(), jacksonTypeRef()) + } catch (e: Exception) { + throw PioneerIntergrationAppInvalidDataException("Error reading response", e) + } + } + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/StringHandler.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/StringHandler.kt new file mode 100644 index 0000000..e93a77f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/handlers/StringHandler.kt @@ -0,0 +1,13 @@ +@file:JvmName("StringHandler") + +package com.pioneer_intergration_app.api.core.handlers + +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler + +internal fun stringHandler(): Handler = StringHandlerInternal + +private object StringHandlerInternal : Handler { + override fun handle(response: HttpResponse): String = + response.body().readBytes().toString(Charsets.UTF_8) +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/Headers.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/Headers.kt new file mode 100644 index 0000000..7dc82b3 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/Headers.kt @@ -0,0 +1,111 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.JsonArray +import com.pioneer_intergration_app.api.core.JsonBoolean +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonNull +import com.pioneer_intergration_app.api.core.JsonNumber +import com.pioneer_intergration_app.api.core.JsonObject +import com.pioneer_intergration_app.api.core.JsonString +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.TreeMap + +class Headers private constructor(private val map: Map>, val size: Int) { + + fun isEmpty(): Boolean = map.isEmpty() + + fun names(): Set = map.keys + + fun values(name: String): List = map[name].orEmpty() + + fun toBuilder(): Builder = Builder().putAll(map) + + companion object { + + fun builder() = Builder() + } + + class Builder internal constructor() { + + private val map: MutableMap> = + TreeMap(String.CASE_INSENSITIVE_ORDER) + private var size: Int = 0 + + fun put(name: String, value: JsonValue): Builder = apply { + when (value) { + is JsonMissing, + is JsonNull -> {} + is JsonBoolean -> put(name, value.value.toString()) + is JsonNumber -> put(name, value.value.toString()) + is JsonString -> put(name, value.value) + is JsonArray -> value.values.forEach { put(name, it) } + is JsonObject -> + value.values.forEach { (nestedName, value) -> put("$name.$nestedName", value) } + } + } + + fun put(name: String, value: String) = apply { + map.getOrPut(name) { mutableListOf() }.add(value) + size++ + } + + fun put(name: String, values: Iterable) = apply { values.forEach { put(name, it) } } + + fun putAll(headers: Map>) = apply { headers.forEach(::put) } + + fun putAll(headers: Headers) = apply { + headers.names().forEach { put(it, headers.values(it)) } + } + + fun replace(name: String, value: String) = apply { + remove(name) + put(name, value) + } + + fun replace(name: String, values: Iterable) = apply { + remove(name) + put(name, values) + } + + fun replaceAll(headers: Map>) = apply { + headers.forEach(::replace) + } + + fun replaceAll(headers: Headers) = apply { + headers.names().forEach { replace(it, headers.values(it)) } + } + + fun remove(name: String) = apply { size -= map.remove(name).orEmpty().size } + + fun removeAll(names: Set) = apply { names.forEach(::remove) } + + fun clear() = apply { + map.clear() + size = 0 + } + + fun build() = + Headers( + map.mapValuesTo(TreeMap(String.CASE_INSENSITIVE_ORDER)) { (_, values) -> + values.toImmutable() + } + .toImmutable(), + size, + ) + } + + override fun hashCode(): Int = map.hashCode() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Headers && map == other.map + } + + override fun toString(): String = "Headers{map=$map}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt new file mode 100644 index 0000000..ae5773b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpClient.kt @@ -0,0 +1,17 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.RequestOptions +import java.lang.AutoCloseable + +interface HttpClient : AutoCloseable { + + fun execute( + request: HttpRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpMethod.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpMethod.kt new file mode 100644 index 0000000..a7b82d7 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpMethod.kt @@ -0,0 +1,13 @@ +package com.pioneer_intergration_app.api.core.http + +enum class HttpMethod { + GET, + HEAD, + POST, + PUT, + DELETE, + CONNECT, + OPTIONS, + TRACE, + PATCH, +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequest.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequest.kt new file mode 100644 index 0000000..83db170 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequest.kt @@ -0,0 +1,175 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.toImmutable +import java.net.URLEncoder + +class HttpRequest +private constructor( + val method: HttpMethod, + val baseUrl: String, + val pathSegments: List, + val headers: Headers, + val queryParams: QueryParams, + val body: HttpRequestBody?, +) { + + fun url(): String = buildString { + append(baseUrl) + + pathSegments.forEach { segment -> + if (!endsWith("/")) { + append("/") + } + append(URLEncoder.encode(segment, "UTF-8")) + } + + if (queryParams.isEmpty()) { + return@buildString + } + + append("?") + var isFirst = true + queryParams.keys().forEach { key -> + queryParams.values(key).forEach { value -> + if (!isFirst) { + append("&") + } + append(URLEncoder.encode(key, "UTF-8")) + append("=") + append(URLEncoder.encode(value, "UTF-8")) + isFirst = false + } + } + } + + fun toBuilder(): Builder = Builder().from(this) + + override fun toString(): String = + "HttpRequest{method=$method, baseUrl=$baseUrl, pathSegments=$pathSegments, headers=$headers, queryParams=$queryParams, body=$body}" + + companion object { + fun builder() = Builder() + } + + class Builder internal constructor() { + + private var method: HttpMethod? = null + private var baseUrl: String? = null + private var pathSegments: MutableList = mutableListOf() + private var headers: Headers.Builder = Headers.builder() + private var queryParams: QueryParams.Builder = QueryParams.builder() + private var body: HttpRequestBody? = null + + internal fun from(request: HttpRequest) = apply { + method = request.method + baseUrl = request.baseUrl + pathSegments = request.pathSegments.toMutableList() + headers = request.headers.toBuilder() + queryParams = request.queryParams.toBuilder() + body = request.body + } + + fun method(method: HttpMethod) = apply { this.method = method } + + fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl } + + fun addPathSegment(pathSegment: String) = apply { pathSegments.add(pathSegment) } + + fun addPathSegments(vararg pathSegments: String) = apply { + this.pathSegments.addAll(pathSegments) + } + + fun headers(headers: Headers) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun headers(headers: Map>) = apply { + this.headers.clear() + putAllHeaders(headers) + } + + fun putHeader(name: String, value: String) = apply { headers.put(name, value) } + + fun putHeaders(name: String, values: Iterable) = apply { headers.put(name, values) } + + fun putAllHeaders(headers: Headers) = apply { this.headers.putAll(headers) } + + fun putAllHeaders(headers: Map>) = apply { + this.headers.putAll(headers) + } + + fun replaceHeaders(name: String, value: String) = apply { headers.replace(name, value) } + + fun replaceHeaders(name: String, values: Iterable) = apply { + headers.replace(name, values) + } + + fun replaceAllHeaders(headers: Headers) = apply { this.headers.replaceAll(headers) } + + fun replaceAllHeaders(headers: Map>) = apply { + this.headers.replaceAll(headers) + } + + fun removeHeaders(name: String) = apply { headers.remove(name) } + + fun removeAllHeaders(names: Set) = apply { headers.removeAll(names) } + + fun queryParams(queryParams: QueryParams) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun queryParams(queryParams: Map>) = apply { + this.queryParams.clear() + putAllQueryParams(queryParams) + } + + fun putQueryParam(key: String, value: String) = apply { queryParams.put(key, value) } + + fun putQueryParams(key: String, values: Iterable) = apply { + queryParams.put(key, values) + } + + fun putAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.putAll(queryParams) + } + + fun putAllQueryParams(queryParams: Map>) = apply { + this.queryParams.putAll(queryParams) + } + + fun replaceQueryParams(key: String, value: String) = apply { + queryParams.replace(key, value) + } + + fun replaceQueryParams(key: String, values: Iterable) = apply { + queryParams.replace(key, values) + } + + fun replaceAllQueryParams(queryParams: QueryParams) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun replaceAllQueryParams(queryParams: Map>) = apply { + this.queryParams.replaceAll(queryParams) + } + + fun removeQueryParams(key: String) = apply { queryParams.remove(key) } + + fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) } + + fun body(body: HttpRequestBody) = apply { this.body = body } + + fun build(): HttpRequest = + HttpRequest( + checkRequired("method", method), + checkRequired("baseUrl", baseUrl), + pathSegments.toImmutable(), + headers.build(), + queryParams.build(), + body, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBodies.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBodies.kt new file mode 100644 index 0000000..4e0c6a5 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBodies.kt @@ -0,0 +1,125 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.json.JsonMapper +import com.fasterxml.jackson.databind.node.JsonNodeType +import com.pioneer_intergration_app.api.core.MultipartField +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.io.InputStream +import java.io.OutputStream +import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder +import org.apache.hc.core5.http.ContentType +import org.apache.hc.core5.http.HttpEntity + +internal inline fun json(jsonMapper: JsonMapper, value: T): HttpRequestBody = + object : HttpRequestBody { + private val bytes: ByteArray by lazy { jsonMapper.writeValueAsBytes(value) } + + override fun writeTo(outputStream: OutputStream) = outputStream.write(bytes) + + override fun contentType(): String = "application/json" + + override fun contentLength(): Long = bytes.size.toLong() + + override fun repeatable(): Boolean = true + + override fun close() {} + } + +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() + 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) -> + addBinaryBody( + name, + bytes, + ContentType.parseLenient(field.contentType), + field.filename, + ) + } + } + } + .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().inputStream()) + JsonNodeType.BOOLEAN -> + sequenceOf(name to node.booleanValue().toString().inputStream()) + JsonNodeType.NUMBER -> + sequenceOf(name to node.numberValue().toString().inputStream()) + JsonNodeType.ARRAY -> + sequenceOf( + name to + node + .elements() + .asSequence() + .mapNotNull { element -> + when (element.nodeType) { + JsonNodeType.MISSING, + JsonNodeType.NULL -> null + JsonNodeType.STRING -> node.textValue() + JsonNodeType.BOOLEAN -> node.booleanValue().toString() + JsonNodeType.NUMBER -> node.numberValue().toString() + null, + JsonNodeType.BINARY, + JsonNodeType.ARRAY, + JsonNodeType.OBJECT, + JsonNodeType.POJO -> + throw PioneerIntergrationAppInvalidDataException( + "Unexpected JsonNode type in array: ${node.nodeType}" + ) + } + } + .joinToString(",") + .inputStream() + ) + JsonNodeType.OBJECT -> + node.fields().asSequence().flatMap { (key, value) -> + serializePart("$name[$key]", value) + } + JsonNodeType.POJO, + null -> + throw PioneerIntergrationAppInvalidDataException( + "Unexpected JsonNode type: ${node.nodeType}" + ) + } + + private fun String.inputStream(): InputStream = toByteArray().inputStream() + + override fun writeTo(outputStream: OutputStream) = entity.writeTo(outputStream) + + override fun contentType(): String = entity.contentType + + override fun contentLength(): Long = entity.contentLength + + override fun repeatable(): Boolean = entity.isRepeatable + + override fun close() = entity.close() + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBody.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBody.kt new file mode 100644 index 0000000..71b845a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestBody.kt @@ -0,0 +1,22 @@ +package com.pioneer_intergration_app.api.core.http + +import java.io.OutputStream +import java.lang.AutoCloseable + +interface HttpRequestBody : AutoCloseable { + + fun writeTo(outputStream: OutputStream) + + fun contentType(): String? + + fun contentLength(): Long + + /** + * Determines if a request can be repeated in a meaningful way, for example before doing a + * retry. + * + * The most typical case when a request can't be retried is if the request body is being + * streamed. In this case the body data isn't available on subsequent attempts. + */ + fun repeatable(): Boolean +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponse.kt new file mode 100644 index 0000000..a01def6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponse.kt @@ -0,0 +1,19 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import java.io.InputStream + +interface HttpResponse : AutoCloseable { + + fun statusCode(): Int + + fun headers(): Headers + + fun body(): InputStream + + interface Handler { + + fun handle(response: HttpResponse): T + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponseFor.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponseFor.kt new file mode 100644 index 0000000..b091b8d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/HttpResponseFor.kt @@ -0,0 +1,24 @@ +package com.pioneer_intergration_app.api.core.http + +import java.io.InputStream + +interface HttpResponseFor : HttpResponse { + + fun parse(): T +} + +internal fun HttpResponse.parseable(parse: () -> T): HttpResponseFor = + object : HttpResponseFor { + + private val parsed: T by lazy { parse() } + + override fun parse(): T = parsed + + override fun statusCode(): Int = this@parseable.statusCode() + + override fun headers(): Headers = this@parseable.headers() + + override fun body(): InputStream = this@parseable.body() + + override fun close() = this@parseable.close() + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingHttpClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingHttpClient.kt new file mode 100644 index 0000000..0c442c8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingHttpClient.kt @@ -0,0 +1,25 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.closeWhenPhantomReachable + +/** + * A delegating wrapper around an `HttpClient` that closes it once it's only phantom reachable. + * + * This class ensures the `HttpClient` is closed even if the user forgets to close it. + */ +internal class PhantomReachableClosingHttpClient(private val httpClient: HttpClient) : HttpClient { + init { + closeWhenPhantomReachable(this, httpClient) + } + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse = + httpClient.execute(request, requestOptions) + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = httpClient.executeAsync(request, requestOptions) + + override fun close() = httpClient.close() +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingStreamResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingStreamResponse.kt new file mode 100644 index 0000000..ff6c2bb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/PhantomReachableClosingStreamResponse.kt @@ -0,0 +1,20 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.closeWhenPhantomReachable + +/** + * A delegating wrapper around a `StreamResponse` that closes it once it's only phantom reachable. + * + * This class ensures the `StreamResponse` is closed even if the user forgets to close it. + */ +internal class PhantomReachableClosingStreamResponse( + private val streamResponse: StreamResponse +) : StreamResponse { + init { + closeWhenPhantomReachable(this, streamResponse) + } + + override fun asSequence(): Sequence = streamResponse.asSequence() + + override fun close() = streamResponse.close() +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/QueryParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/QueryParams.kt new file mode 100644 index 0000000..58081ab --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/QueryParams.kt @@ -0,0 +1,125 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.JsonArray +import com.pioneer_intergration_app.api.core.JsonBoolean +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonNull +import com.pioneer_intergration_app.api.core.JsonNumber +import com.pioneer_intergration_app.api.core.JsonObject +import com.pioneer_intergration_app.api.core.JsonString +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.toImmutable + +class QueryParams private constructor(private val map: Map>, val size: Int) { + + fun isEmpty(): Boolean = map.isEmpty() + + fun keys(): Set = map.keys + + fun values(key: String): List = map[key].orEmpty() + + fun toBuilder(): Builder = Builder().putAll(map) + + companion object { + + fun builder() = Builder() + } + + class Builder internal constructor() { + + private val map: MutableMap> = mutableMapOf() + private var size: Int = 0 + + fun put(key: String, value: JsonValue): Builder = apply { + when (value) { + is JsonMissing, + is JsonNull -> {} + is JsonBoolean -> put(key, value.value.toString()) + is JsonNumber -> put(key, value.value.toString()) + is JsonString -> put(key, value.value) + is JsonArray -> + put( + key, + value.values + .asSequence() + .mapNotNull { + when (it) { + is JsonMissing, + is JsonNull -> null + is JsonBoolean -> it.value.toString() + is JsonNumber -> it.value.toString() + is JsonString -> it.value + is JsonArray, + is JsonObject -> + throw IllegalArgumentException( + "Cannot comma separate non-primitives in query params" + ) + } + } + .joinToString(","), + ) + is JsonObject -> + value.values.forEach { (nestedKey, value) -> put("$key[$nestedKey]", value) } + } + } + + fun put(key: String, value: String) = apply { + map.getOrPut(key) { mutableListOf() }.add(value) + size++ + } + + fun put(key: String, values: Iterable) = apply { values.forEach { put(key, it) } } + + fun putAll(queryParams: Map>) = apply { + queryParams.forEach(::put) + } + + fun putAll(queryParams: QueryParams) = apply { + queryParams.keys().forEach { put(it, queryParams.values(it)) } + } + + fun replace(key: String, value: String) = apply { + remove(key) + put(key, value) + } + + fun replace(key: String, values: Iterable) = apply { + remove(key) + put(key, values) + } + + fun replaceAll(queryParams: Map>) = apply { + queryParams.forEach(::replace) + } + + fun replaceAll(queryParams: QueryParams) = apply { + queryParams.keys().forEach { replace(it, queryParams.values(it)) } + } + + fun remove(key: String) = apply { size -= map.remove(key).orEmpty().size } + + fun removeAll(keys: Set) = apply { keys.forEach(::remove) } + + fun clear() = apply { + map.clear() + size = 0 + } + + fun build() = + QueryParams(map.mapValues { (_, values) -> values.toImmutable() }.toImmutable(), size) + } + + override fun hashCode(): Int = map.hashCode() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is QueryParams && map == other.map + } + + override fun toString(): String = "QueryParams{map=$map}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt new file mode 100644 index 0000000..1b76c92 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt @@ -0,0 +1,248 @@ +package com.pioneer_intergration_app.api.core.http + +import com.pioneer_intergration_app.api.core.DefaultSleeper +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppIoException +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppRetryableException +import java.io.IOException +import java.time.Clock +import java.time.Duration +import java.time.OffsetDateTime +import java.time.format.DateTimeFormatter +import java.time.format.DateTimeParseException +import java.time.temporal.ChronoUnit +import java.util.UUID +import java.util.concurrent.ThreadLocalRandom +import java.util.concurrent.TimeUnit +import kotlin.math.min +import kotlin.math.pow + +class RetryingHttpClient +private constructor( + private val httpClient: HttpClient, + private val sleeper: Sleeper, + private val clock: Clock, + private val maxRetries: Int, + private val idempotencyHeader: String?, +) : HttpClient { + + override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { + if (!isRetryable(request) || maxRetries <= 0) { + return httpClient.execute(request, requestOptions) + } + + var modifiedRequest = maybeAddIdempotencyHeader(request) + + // Don't send the current retry count in the headers if the caller set their own value. + val shouldSendRetryCount = + !modifiedRequest.headers.names().contains("X-Stainless-Retry-Count") + + var retries = 0 + + while (true) { + if (shouldSendRetryCount) { + modifiedRequest = setRetryCountHeader(modifiedRequest, retries) + } + + val response = + try { + val response = httpClient.execute(modifiedRequest, requestOptions) + if (++retries > maxRetries || !shouldRetry(response)) { + return response + } + + response + } catch (throwable: Throwable) { + if (++retries > maxRetries || !shouldRetry(throwable)) { + throw throwable + } + + null + } + + val backoffDuration = getRetryBackoffDuration(retries, response) + // All responses must be closed, so close the failed one before retrying. + response?.close() + sleeper.sleep(backoffDuration) + } + } + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + if (!isRetryable(request) || maxRetries <= 0) { + return httpClient.executeAsync(request, requestOptions) + } + + var modifiedRequest = maybeAddIdempotencyHeader(request) + + // Don't send the current retry count in the headers if the caller set their own value. + val shouldSendRetryCount = + !modifiedRequest.headers.names().contains("X-Stainless-Retry-Count") + + var retries = 0 + + while (true) { + if (shouldSendRetryCount) { + modifiedRequest = setRetryCountHeader(modifiedRequest, retries) + } + + val response = + try { + val response = httpClient.execute(modifiedRequest, requestOptions) + if (++retries > maxRetries || !shouldRetry(response)) { + return response + } + + response + } catch (throwable: Throwable) { + if (++retries > maxRetries || !shouldRetry(throwable)) { + throw throwable + } + + null + } + + val backoffDuration = getRetryBackoffDuration(retries, response) + // All responses must be closed, so close the failed one before retrying. + response?.close() + sleeper.sleepAsync(backoffDuration) + } + } + + override fun close() { + httpClient.close() + sleeper.close() + } + + private fun isRetryable(request: HttpRequest): Boolean = + // Some requests, such as when a request body is being streamed, cannot be retried because + // the body data aren't available on subsequent attempts. + request.body?.repeatable() ?: true + + private fun setRetryCountHeader(request: HttpRequest, retries: Int): HttpRequest = + request.toBuilder().replaceHeaders("X-Stainless-Retry-Count", retries.toString()).build() + + private fun idempotencyKey(): String = "stainless-java-retry-${UUID.randomUUID()}" + + private fun maybeAddIdempotencyHeader(request: HttpRequest): HttpRequest { + if (idempotencyHeader == null || request.headers.names().contains(idempotencyHeader)) { + return request + } + + return request + .toBuilder() + // Set a header to uniquely identify the request when retried + .putHeader(idempotencyHeader, idempotencyKey()) + .build() + } + + private fun shouldRetry(response: HttpResponse): Boolean { + // Note: this is not a standard header + val shouldRetryHeader = response.headers().values("X-Should-Retry").getOrNull(0) + val statusCode = response.statusCode() + + return when { + // If the server explicitly says whether to retry, obey + shouldRetryHeader == "true" -> true + shouldRetryHeader == "false" -> false + + // Retry on request timeouts + statusCode == 408 -> true + // Retry on lock timeouts + statusCode == 409 -> true + // Retry on rate limits + statusCode == 429 -> true + // Retry internal errors + statusCode >= 500 -> true + else -> false + } + } + + private fun shouldRetry(throwable: Throwable): Boolean = + // Only retry known retryable exceptions, other exceptions are not intended to be retried. + throwable is IOException || + throwable is PioneerIntergrationAppIoException || + throwable is PioneerIntergrationAppRetryableException + + private fun getRetryBackoffDuration(retries: Int, response: HttpResponse?): Duration { + // About the Retry-After header: + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + response + ?.headers() + ?.let { headers -> + headers + .values("Retry-After-Ms") + .getOrNull(0) + ?.toFloatOrNull() + ?.times(TimeUnit.MILLISECONDS.toNanos(1)) + ?: headers.values("Retry-After").getOrNull(0)?.let { retryAfter -> + retryAfter.toFloatOrNull()?.times(TimeUnit.SECONDS.toNanos(1)) + ?: try { + ChronoUnit.MILLIS.between( + OffsetDateTime.now(clock), + OffsetDateTime.parse( + retryAfter, + DateTimeFormatter.RFC_1123_DATE_TIME, + ), + ) + } catch (e: DateTimeParseException) { + null + } + } + } + ?.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 + } + } + + // Apply exponential backoff, but not more than the max. + val backoffSeconds = min(0.5 * 2.0.pow(retries - 1), 8.0) + + // Apply some jitter + val jitter = 1.0 - 0.25 * ThreadLocalRandom.current().nextDouble() + + return Duration.ofNanos((TimeUnit.SECONDS.toNanos(1) * backoffSeconds * jitter).toLong()) + } + + companion object { + + fun builder() = Builder() + } + + class Builder internal constructor() { + + private var httpClient: HttpClient? = null + private var sleeper: Sleeper? = null + private var clock: Clock = Clock.systemUTC() + private var maxRetries: Int = 2 + private var idempotencyHeader: String? = null + + fun httpClient(httpClient: HttpClient) = apply { this.httpClient = httpClient } + + fun sleeper(sleeper: Sleeper) = apply { this.sleeper = sleeper } + + fun clock(clock: Clock) = apply { this.clock = clock } + + fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } + + fun idempotencyHeader(header: String) = apply { this.idempotencyHeader = header } + + fun build(): HttpClient = + RetryingHttpClient( + checkRequired("httpClient", httpClient), + sleeper ?: DefaultSleeper(), + clock, + maxRetries, + idempotencyHeader, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/StreamResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/StreamResponse.kt new file mode 100644 index 0000000..6b984f6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/StreamResponse.kt @@ -0,0 +1,13 @@ +package com.pioneer_intergration_app.api.core.http + +interface StreamResponse : AutoCloseable { + + fun asSequence(): Sequence +} + +internal fun StreamResponse.map(transform: (T) -> R): StreamResponse = + object : StreamResponse { + override fun asSequence(): Sequence = this@map.asSequence().map(transform) + + override fun close() = this@map.close() + } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt new file mode 100644 index 0000000..edc6559 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/BadRequestException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class BadRequestException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("400: $body", cause) { + + override fun statusCode(): Int = 400 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [BadRequestException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [BadRequestException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(badRequestException: BadRequestException) = apply { + headers = badRequestException.headers + body = badRequestException.body + cause = badRequestException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [BadRequestException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): BadRequestException = + BadRequestException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt new file mode 100644 index 0000000..73c61e8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/InternalServerException.kt @@ -0,0 +1,85 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class InternalServerException +private constructor( + private val statusCode: Int, + private val headers: Headers, + private val body: JsonValue, + cause: Throwable?, +) : PioneerIntergrationAppServiceException("$statusCode: $body", cause) { + + override fun statusCode(): Int = statusCode + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [InternalServerException]. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [InternalServerException]. */ + class Builder internal constructor() { + + private var statusCode: Int? = null + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(internalServerException: InternalServerException) = apply { + statusCode = internalServerException.statusCode + headers = internalServerException.headers + body = internalServerException.body + cause = internalServerException.cause + } + + fun statusCode(statusCode: Int) = apply { this.statusCode = statusCode } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [InternalServerException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): InternalServerException = + InternalServerException( + checkRequired("statusCode", statusCode), + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt new file mode 100644 index 0000000..6761c18 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/NotFoundException.kt @@ -0,0 +1,70 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class NotFoundException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("404: $body", cause) { + + override fun statusCode(): Int = 404 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [NotFoundException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [NotFoundException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(notFoundException: NotFoundException) = apply { + headers = notFoundException.headers + body = notFoundException.body + cause = notFoundException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [NotFoundException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): NotFoundException = + NotFoundException(checkRequired("headers", headers), checkRequired("body", body), cause) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt new file mode 100644 index 0000000..73812ac --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PermissionDeniedException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class PermissionDeniedException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("403: $body", cause) { + + override fun statusCode(): Int = 403 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PermissionDeniedException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [PermissionDeniedException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(permissionDeniedException: PermissionDeniedException) = apply { + headers = permissionDeniedException.headers + body = permissionDeniedException.body + cause = permissionDeniedException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [PermissionDeniedException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PermissionDeniedException = + PermissionDeniedException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt new file mode 100644 index 0000000..c573765 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppException.kt @@ -0,0 +1,4 @@ +package com.pioneer_intergration_app.api.errors + +open class PioneerIntergrationAppException(message: String? = null, cause: Throwable? = null) : + RuntimeException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt new file mode 100644 index 0000000..e5ccb27 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppInvalidDataException.kt @@ -0,0 +1,6 @@ +package com.pioneer_intergration_app.api.errors + +class PioneerIntergrationAppInvalidDataException( + message: String? = null, + cause: Throwable? = null, +) : PioneerIntergrationAppException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt new file mode 100644 index 0000000..cc510dd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppIoException.kt @@ -0,0 +1,4 @@ +package com.pioneer_intergration_app.api.errors + +class PioneerIntergrationAppIoException(message: String? = null, cause: Throwable? = null) : + PioneerIntergrationAppException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt new file mode 100644 index 0000000..35c0377 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppRetryableException.kt @@ -0,0 +1,14 @@ +package com.pioneer_intergration_app.api.errors + +/** + * Exception that indicates a transient error that can be retried. + * + * When this exception is thrown during an HTTP request, the SDK will automatically retry the + * request up to the maximum number of retries. + * + * @param message A descriptive error message + * @param cause The underlying cause of this exception, if any + */ +class PioneerIntergrationAppRetryableException +constructor(message: String? = null, cause: Throwable? = null) : + PioneerIntergrationAppException(message, cause) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt new file mode 100644 index 0000000..d6a1afb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/PioneerIntergrationAppServiceException.kt @@ -0,0 +1,17 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.http.Headers + +abstract class PioneerIntergrationAppServiceException +protected constructor(message: String, cause: Throwable? = null) : + PioneerIntergrationAppException(message, cause) { + + abstract fun statusCode(): Int + + abstract fun headers(): Headers + + abstract fun body(): JsonValue +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt new file mode 100644 index 0000000..0da4d02 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/RateLimitException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class RateLimitException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("429: $body", cause) { + + override fun statusCode(): Int = 429 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [RateLimitException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [RateLimitException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(rateLimitException: RateLimitException) = apply { + headers = rateLimitException.headers + body = rateLimitException.body + cause = rateLimitException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [RateLimitException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): RateLimitException = + RateLimitException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt new file mode 100644 index 0000000..aee9969 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnauthorizedException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class UnauthorizedException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("401: $body", cause) { + + override fun statusCode(): Int = 401 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [UnauthorizedException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [UnauthorizedException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(unauthorizedException: UnauthorizedException) = apply { + headers = unauthorizedException.headers + body = unauthorizedException.body + cause = unauthorizedException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [UnauthorizedException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UnauthorizedException = + UnauthorizedException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt new file mode 100644 index 0000000..535bf2a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnexpectedStatusCodeException.kt @@ -0,0 +1,86 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class UnexpectedStatusCodeException +private constructor( + private val statusCode: Int, + private val headers: Headers, + private val body: JsonValue, + cause: Throwable?, +) : PioneerIntergrationAppServiceException("$statusCode: $body", cause) { + + override fun statusCode(): Int = statusCode + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of + * [UnexpectedStatusCodeException]. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [UnexpectedStatusCodeException]. */ + class Builder internal constructor() { + + private var statusCode: Int? = null + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(unexpectedStatusCodeException: UnexpectedStatusCodeException) = apply { + statusCode = unexpectedStatusCodeException.statusCode + headers = unexpectedStatusCodeException.headers + body = unexpectedStatusCodeException.body + cause = unexpectedStatusCodeException.cause + } + + fun statusCode(statusCode: Int) = apply { this.statusCode = statusCode } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [UnexpectedStatusCodeException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .statusCode() + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UnexpectedStatusCodeException = + UnexpectedStatusCodeException( + checkRequired("statusCode", statusCode), + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt new file mode 100644 index 0000000..349796d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/errors/UnprocessableEntityException.kt @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.errors + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers + +class UnprocessableEntityException +private constructor(private val headers: Headers, private val body: JsonValue, cause: Throwable?) : + PioneerIntergrationAppServiceException("422: $body", cause) { + + override fun statusCode(): Int = 422 + + override fun headers(): Headers = headers + + override fun body(): JsonValue = body + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [UnprocessableEntityException]. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [UnprocessableEntityException]. */ + class Builder internal constructor() { + + private var headers: Headers? = null + private var body: JsonValue? = null + private var cause: Throwable? = null + + internal fun from(unprocessableEntityException: UnprocessableEntityException) = apply { + headers = unprocessableEntityException.headers + body = unprocessableEntityException.body + cause = unprocessableEntityException.cause + } + + fun headers(headers: Headers) = apply { this.headers = headers } + + fun body(body: JsonValue) = apply { this.body = body } + + fun cause(cause: Throwable?) = apply { this.cause = cause } + + /** + * Returns an immutable instance of [UnprocessableEntityException]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .headers() + * .body() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): UnprocessableEntityException = + UnprocessableEntityException( + checkRequired("headers", headers), + checkRequired("body", body), + cause, + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/Order.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/Order.kt new file mode 100644 index 0000000..1ebbfcd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/Order.kt @@ -0,0 +1,454 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.Enum +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.time.OffsetDateTime +import java.util.Collections +import java.util.Objects + +class Order +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val complete: JsonField, + private val petId: JsonField, + private val quantity: JsonField, + private val shipDate: JsonField, + private val status: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("complete") @ExcludeMissing complete: JsonField = JsonMissing.of(), + @JsonProperty("petId") @ExcludeMissing petId: JsonField = JsonMissing.of(), + @JsonProperty("quantity") @ExcludeMissing quantity: JsonField = JsonMissing.of(), + @JsonProperty("shipDate") + @ExcludeMissing + shipDate: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + ) : this(id, complete, petId, quantity, shipDate, status, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun complete(): Boolean? = complete.getNullable("complete") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun petId(): Long? = petId.getNullable("petId") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun quantity(): Int? = quantity.getNullable("quantity") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun shipDate(): OffsetDateTime? = shipDate.getNullable("shipDate") + + /** + * Order Status + * + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun status(): Status? = status.getNullable("status") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [complete]. + * + * Unlike [complete], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("complete") @ExcludeMissing fun _complete(): JsonField = complete + + /** + * Returns the raw JSON value of [petId]. + * + * Unlike [petId], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("petId") @ExcludeMissing fun _petId(): JsonField = petId + + /** + * Returns the raw JSON value of [quantity]. + * + * Unlike [quantity], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("quantity") @ExcludeMissing fun _quantity(): JsonField = quantity + + /** + * Returns the raw JSON value of [shipDate]. + * + * Unlike [shipDate], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("shipDate") @ExcludeMissing fun _shipDate(): JsonField = shipDate + + /** + * 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) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Order]. */ + fun builder() = Builder() + } + + /** A builder for [Order]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var complete: JsonField = JsonMissing.of() + private var petId: JsonField = JsonMissing.of() + private var quantity: JsonField = JsonMissing.of() + private var shipDate: JsonField = JsonMissing.of() + private var status: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(order: Order) = apply { + id = order.id + complete = order.complete + petId = order.petId + quantity = order.quantity + shipDate = order.shipDate + status = order.status + additionalProperties = order.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun complete(complete: Boolean) = complete(JsonField.of(complete)) + + /** + * Sets [Builder.complete] to an arbitrary JSON value. + * + * You should usually call [Builder.complete] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun complete(complete: JsonField) = apply { this.complete = complete } + + fun petId(petId: Long) = petId(JsonField.of(petId)) + + /** + * Sets [Builder.petId] to an arbitrary JSON value. + * + * You should usually call [Builder.petId] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun petId(petId: JsonField) = apply { this.petId = petId } + + fun quantity(quantity: Int) = quantity(JsonField.of(quantity)) + + /** + * Sets [Builder.quantity] to an arbitrary JSON value. + * + * You should usually call [Builder.quantity] with a well-typed [Int] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun quantity(quantity: JsonField) = apply { this.quantity = quantity } + + fun shipDate(shipDate: OffsetDateTime) = shipDate(JsonField.of(shipDate)) + + /** + * Sets [Builder.shipDate] to an arbitrary JSON value. + * + * You should usually call [Builder.shipDate] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun shipDate(shipDate: JsonField) = apply { this.shipDate = shipDate } + + /** Order Status */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] 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) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Order]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Order = + Order( + id, + complete, + petId, + quantity, + shipDate, + status, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Order = apply { + if (validated) { + return@apply + } + + id() + complete() + petId() + quantity() + shipDate() + status()?.validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + + (if (complete.asKnown() == null) 0 else 1) + + (if (petId.asKnown() == null) 0 else 1) + + (if (quantity.asKnown() == null) 0 else 1) + + (if (shipDate.asKnown() == null) 0 else 1) + + (status.asKnown()?.validity() ?: 0) + + /** Order Status */ + class Status @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + val PLACED = of("placed") + + val APPROVED = of("approved") + + val DELIVERED = of("delivered") + + fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + PLACED, + APPROVED, + DELIVERED, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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 { + PLACED, + APPROVED, + DELIVERED, + /** An enum member indicating that [Status] 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) { + PLACED -> Value.PLACED + APPROVED -> Value.APPROVED + DELIVERED -> Value.DELIVERED + 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 PioneerIntergrationAppInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + PLACED -> Known.PLACED + APPROVED -> Known.APPROVED + DELIVERED -> Known.DELIVERED + else -> throw PioneerIntergrationAppInvalidDataException("Unknown Status: $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 PioneerIntergrationAppInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString() + ?: throw PioneerIntergrationAppInvalidDataException("Value is not a String") + + private var validated: Boolean = false + + fun validate(): Status = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Status && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Order && + id == other.id && + complete == other.complete && + petId == other.petId && + quantity == other.quantity && + shipDate == other.shipDate && + status == other.status && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(id, complete, petId, quantity, shipDate, status, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Order{id=$id, complete=$complete, petId=$petId, quantity=$quantity, shipDate=$shipDate, status=$status, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Category.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Category.kt new file mode 100644 index 0000000..b18051c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Category.kt @@ -0,0 +1,180 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class Category +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(id, name, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun name(): String? = name.getNullable("name") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Category]. */ + fun builder() = Builder() + } + + /** A builder for [Category]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(category: Category) = apply { + id = category.id + name = category.name + additionalProperties = category.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Category]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Category = Category(id, name, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Category = apply { + if (validated) { + return@apply + } + + id() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + (if (name.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Category && + id == other.id && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Category{id=$id, name=$name, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Pet.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Pet.kt new file mode 100644 index 0000000..2fb2c5d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/Pet.kt @@ -0,0 +1,663 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.Enum +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.checkKnown +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.toImmutable +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class Pet +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val name: JsonField, + private val photoUrls: JsonField>, + private val id: JsonField, + private val category: JsonField, + private val status: JsonField, + private val tags: JsonField>, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("photoUrls") + @ExcludeMissing + photoUrls: JsonField> = JsonMissing.of(), + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("category") @ExcludeMissing category: JsonField = JsonMissing.of(), + @JsonProperty("status") @ExcludeMissing status: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + ) : this(name, photoUrls, id, category, status, tags, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * or is unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") + + /** + * @throws PioneerIntergrationAppInvalidDataException 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 photoUrls(): List = photoUrls.getRequired("photoUrls") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun category(): Category? = category.getNullable("category") + + /** + * pet status in the store + * + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun status(): Status? = status.getNullable("status") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun tags(): List? = tags.getNullable("tags") + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Returns the raw JSON value of [photoUrls]. + * + * Unlike [photoUrls], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("photoUrls") @ExcludeMissing fun _photoUrls(): JsonField> = photoUrls + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [category]. + * + * Unlike [category], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("category") @ExcludeMissing fun _category(): JsonField = category + + /** + * 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 + + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Pet]. + * + * The following fields are required: + * ```kotlin + * .name() + * .photoUrls() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [Pet]. */ + class Builder internal constructor() { + + private var name: JsonField? = null + private var photoUrls: JsonField>? = null + private var id: JsonField = JsonMissing.of() + private var category: JsonField = JsonMissing.of() + private var status: JsonField = JsonMissing.of() + private var tags: JsonField>? = null + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(pet: Pet) = apply { + name = pet.name + photoUrls = pet.photoUrls.map { it.toMutableList() } + id = pet.id + category = pet.category + status = pet.status + tags = pet.tags.map { it.toMutableList() } + additionalProperties = pet.additionalProperties.toMutableMap() + } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun photoUrls(photoUrls: List) = photoUrls(JsonField.of(photoUrls)) + + /** + * Sets [Builder.photoUrls] to an arbitrary JSON value. + * + * You should usually call [Builder.photoUrls] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun photoUrls(photoUrls: JsonField>) = apply { + this.photoUrls = photoUrls.map { it.toMutableList() } + } + + /** + * Adds a single [String] to [photoUrls]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addPhotoUrl(photoUrl: String) = apply { + photoUrls = + (photoUrls ?: JsonField.of(mutableListOf())).also { + checkKnown("photoUrls", it).add(photoUrl) + } + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun category(category: Category) = category(JsonField.of(category)) + + /** + * Sets [Builder.category] to an arbitrary JSON value. + * + * You should usually call [Builder.category] with a well-typed [Category] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun category(category: JsonField) = apply { this.category = category } + + /** pet status in the store */ + fun status(status: Status) = status(JsonField.of(status)) + + /** + * Sets [Builder.status] to an arbitrary JSON value. + * + * You should usually call [Builder.status] with a well-typed [Status] 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 tags(tags: List) = tags(JsonField.of(tags)) + + /** + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun tags(tags: JsonField>) = apply { this.tags = tags.map { it.toMutableList() } } + + /** + * Adds a single [Tag] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: Tag) = apply { + tags = (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Pet]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .name() + * .photoUrls() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Pet = + Pet( + checkRequired("name", name), + checkRequired("photoUrls", photoUrls).map { it.toImmutable() }, + id, + category, + status, + (tags ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): Pet = apply { + if (validated) { + return@apply + } + + name() + photoUrls() + id() + category()?.validate() + status()?.validate() + tags()?.forEach { it.validate() } + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (name.asKnown() == null) 0 else 1) + + (photoUrls.asKnown()?.size ?: 0) + + (if (id.asKnown() == null) 0 else 1) + + (category.asKnown()?.validity() ?: 0) + + (status.asKnown()?.validity() ?: 0) + + (tags.asKnown()?.sumOf { it.validity().toInt() } ?: 0) + + /** pet status in the store */ + class Status @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + val AVAILABLE = of("available") + + val PENDING = of("pending") + + val SOLD = of("sold") + + fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + AVAILABLE, + PENDING, + SOLD, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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 { + AVAILABLE, + PENDING, + SOLD, + /** An enum member indicating that [Status] 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) { + AVAILABLE -> Value.AVAILABLE + PENDING -> Value.PENDING + SOLD -> Value.SOLD + 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 PioneerIntergrationAppInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + AVAILABLE -> Known.AVAILABLE + PENDING -> Known.PENDING + SOLD -> Known.SOLD + else -> throw PioneerIntergrationAppInvalidDataException("Unknown Status: $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 PioneerIntergrationAppInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString() + ?: throw PioneerIntergrationAppInvalidDataException("Value is not a String") + + private var validated: Boolean = false + + fun validate(): Status = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Status && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + class Tag + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val id: JsonField, + private val name: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + ) : this(id, name, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected + * type (e.g. if the server responded with an unexpected value). + */ + fun name(): String? = name.getNullable("name") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [Tag]. */ + fun builder() = Builder() + } + + /** A builder for [Tag]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(tag: Tag) = apply { + id = tag.id + name = tag.name + additionalProperties = tag.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun name(name: String) = name(JsonField.of(name)) + + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun name(name: JsonField) = apply { this.name = name } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Tag]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): Tag = Tag(id, name, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): Tag = apply { + if (validated) { + return@apply + } + + id() + name() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + (if (name.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Tag && + id == other.id && + name == other.name && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(id, name, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Tag{id=$id, name=$name, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Pet && + name == other.name && + photoUrls == other.photoUrls && + id == other.id && + category == other.category && + status == other.status && + tags == other.tags && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(name, photoUrls, id, category, status, tags, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Pet{name=$name, photoUrls=$photoUrls, id=$id, category=$category, status=$status, tags=$tags, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParams.kt new file mode 100644 index 0000000..03b309b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParams.kt @@ -0,0 +1,199 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Add a new pet to the store */ +class PetCreateParams +private constructor( + private val pet: Pet, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun pet(): Pet = pet + + fun _additionalBodyProperties(): Map = pet._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PetCreateParams]. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [PetCreateParams]. */ + class Builder internal constructor() { + + private var pet: Pet? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petCreateParams: PetCreateParams) = apply { + pet = petCreateParams.pet + additionalHeaders = petCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = petCreateParams.additionalQueryParams.toBuilder() + } + + fun pet(pet: Pet) = apply { this.pet = pet } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PetCreateParams = + PetCreateParams( + checkRequired("pet", pet), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Pet = pet + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetCreateParams && + pet == other.pet && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(pet, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetCreateParams{pet=$pet, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParams.kt new file mode 100644 index 0000000..141949a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParams.kt @@ -0,0 +1,229 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** delete a pet */ +class PetDeleteParams +private constructor( + private val petId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun petId(): Long? = petId + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetDeleteParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetDeleteParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(petDeleteParams: PetDeleteParams) = apply { + petId = petDeleteParams.petId + additionalHeaders = petDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = petDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = petDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [PetDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetDeleteParams = + PetDeleteParams( + petId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetDeleteParams && + petId == other.petId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(petId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "PetDeleteParams{petId=$petId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParams.kt new file mode 100644 index 0000000..e3f92ea --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParams.kt @@ -0,0 +1,322 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonCreator +import com.pioneer_intergration_app.api.core.Enum +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Objects + +/** Multiple status values can be provided with comma separated strings */ +class PetFindByStatusParams +private constructor( + private val status: Status?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Status values that need to be considered for filter */ + fun status(): Status? = status + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetFindByStatusParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetFindByStatusParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetFindByStatusParams]. */ + class Builder internal constructor() { + + private var status: Status? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petFindByStatusParams: PetFindByStatusParams) = apply { + status = petFindByStatusParams.status + additionalHeaders = petFindByStatusParams.additionalHeaders.toBuilder() + additionalQueryParams = petFindByStatusParams.additionalQueryParams.toBuilder() + } + + /** Status values that need to be considered for filter */ + fun status(status: Status?) = apply { this.status = status } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetFindByStatusParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetFindByStatusParams = + PetFindByStatusParams(status, additionalHeaders.build(), additionalQueryParams.build()) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + status?.let { put("status", it.toString()) } + putAll(additionalQueryParams) + } + .build() + + /** Status values that need to be considered for filter */ + class Status @JsonCreator private constructor(private val value: JsonField) : Enum { + + /** + * Returns this class instance's raw value. + * + * This is usually only useful if this instance was deserialized from data that doesn't + * match any known member, and you want to know that value. For example, if the SDK is on an + * older version than the API, then the API may respond with new members that the SDK is + * unaware of. + */ + @com.fasterxml.jackson.annotation.JsonValue fun _value(): JsonField = value + + companion object { + + val AVAILABLE = of("available") + + val PENDING = of("pending") + + val SOLD = of("sold") + + fun of(value: String) = Status(JsonField.of(value)) + } + + /** An enum containing [Status]'s known values. */ + enum class Known { + AVAILABLE, + PENDING, + SOLD, + } + + /** + * An enum containing [Status]'s known values, as well as an [_UNKNOWN] member. + * + * An instance of [Status] 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 { + AVAILABLE, + PENDING, + SOLD, + /** An enum member indicating that [Status] 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) { + AVAILABLE -> Value.AVAILABLE + PENDING -> Value.PENDING + SOLD -> Value.SOLD + 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 PioneerIntergrationAppInvalidDataException if this class instance's value is a + * not a known member. + */ + fun known(): Known = + when (this) { + AVAILABLE -> Known.AVAILABLE + PENDING -> Known.PENDING + SOLD -> Known.SOLD + else -> throw PioneerIntergrationAppInvalidDataException("Unknown Status: $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 PioneerIntergrationAppInvalidDataException if this class instance's value does + * not have the expected primitive type. + */ + fun asString(): String = + _value().asString() + ?: throw PioneerIntergrationAppInvalidDataException("Value is not a String") + + private var validated: Boolean = false + + fun validate(): Status = apply { + if (validated) { + return@apply + } + + known() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Status && value == other.value + } + + override fun hashCode() = value.hashCode() + + override fun toString() = value.toString() + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetFindByStatusParams && + status == other.status && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(status, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetFindByStatusParams{status=$status, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParams.kt new file mode 100644 index 0000000..cc8a749 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParams.kt @@ -0,0 +1,197 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. */ +class PetFindByTagsParams +private constructor( + private val tags: List?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Tags to filter by */ + fun tags(): List? = tags + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetFindByTagsParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetFindByTagsParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetFindByTagsParams]. */ + class Builder internal constructor() { + + private var tags: MutableList? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petFindByTagsParams: PetFindByTagsParams) = apply { + tags = petFindByTagsParams.tags?.toMutableList() + additionalHeaders = petFindByTagsParams.additionalHeaders.toBuilder() + additionalQueryParams = petFindByTagsParams.additionalQueryParams.toBuilder() + } + + /** Tags to filter by */ + fun tags(tags: List?) = apply { this.tags = tags?.toMutableList() } + + /** + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addTag(tag: String) = apply { tags = (tags ?: mutableListOf()).apply { add(tag) } } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetFindByTagsParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetFindByTagsParams = + PetFindByTagsParams( + tags?.toImmutable(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + tags?.let { put("tags", it.joinToString(",")) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetFindByTagsParams && + tags == other.tags && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(tags, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetFindByTagsParams{tags=$tags, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParams.kt new file mode 100644 index 0000000..830b00f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParams.kt @@ -0,0 +1,190 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Returns a single pet */ +class PetRetrieveParams +private constructor( + private val petId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun petId(): Long? = petId + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetRetrieveParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetRetrieveParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petRetrieveParams: PetRetrieveParams) = apply { + petId = petRetrieveParams.petId + additionalHeaders = petRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = petRetrieveParams.additionalQueryParams.toBuilder() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetRetrieveParams = + PetRetrieveParams(petId, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetRetrieveParams && + petId == other.petId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(petId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetRetrieveParams{petId=$petId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParams.kt new file mode 100644 index 0000000..489ca8c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParams.kt @@ -0,0 +1,265 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** Updates a pet in the store with form data */ +class PetUpdateByIdParams +private constructor( + private val petId: Long?, + private val name: String?, + private val status: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun petId(): Long? = petId + + /** Name of pet that needs to be updated */ + fun name(): String? = name + + /** Status of pet that needs to be updated */ + fun status(): String? = status + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetUpdateByIdParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetUpdateByIdParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetUpdateByIdParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var name: String? = null + private var status: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(petUpdateByIdParams: PetUpdateByIdParams) = apply { + petId = petUpdateByIdParams.petId + name = petUpdateByIdParams.name + status = petUpdateByIdParams.status + additionalHeaders = petUpdateByIdParams.additionalHeaders.toBuilder() + additionalQueryParams = petUpdateByIdParams.additionalQueryParams.toBuilder() + additionalBodyProperties = petUpdateByIdParams.additionalBodyProperties.toMutableMap() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + /** Name of pet that needs to be updated */ + fun name(name: String?) = apply { this.name = name } + + /** Status of pet that needs to be updated */ + fun status(status: String?) = apply { this.status = status } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [PetUpdateByIdParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetUpdateByIdParams = + PetUpdateByIdParams( + petId, + name, + status, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + name?.let { put("name", it) } + status?.let { put("status", it) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUpdateByIdParams && + petId == other.petId && + name == other.name && + status == other.status && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash( + petId, + name, + status, + additionalHeaders, + additionalQueryParams, + additionalBodyProperties, + ) + + override fun toString() = + "PetUpdateByIdParams{petId=$petId, name=$name, status=$status, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParams.kt new file mode 100644 index 0000000..32576e6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParams.kt @@ -0,0 +1,199 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Update an existing pet by Id */ +class PetUpdateParams +private constructor( + private val pet: Pet, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun pet(): Pet = pet + + fun _additionalBodyProperties(): Map = pet._additionalProperties() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [PetUpdateParams]. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + */ + fun builder() = Builder() + } + + /** A builder for [PetUpdateParams]. */ + class Builder internal constructor() { + + private var pet: Pet? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petUpdateParams: PetUpdateParams) = apply { + pet = petUpdateParams.pet + additionalHeaders = petUpdateParams.additionalHeaders.toBuilder() + additionalQueryParams = petUpdateParams.additionalQueryParams.toBuilder() + } + + fun pet(pet: Pet) = apply { this.pet = pet } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetUpdateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```kotlin + * .pet() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): PetUpdateParams = + PetUpdateParams( + checkRequired("pet", pet), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): Pet = pet + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUpdateParams && + pet == other.pet && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(pet, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetUpdateParams{pet=$pet, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParams.kt new file mode 100644 index 0000000..1187384 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParams.kt @@ -0,0 +1,225 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** uploads an image */ +class PetUploadImageParams +private constructor( + private val petId: Long?, + private val additionalMetadata: String?, + private val image: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun petId(): Long? = petId + + /** Additional Metadata */ + fun additionalMetadata(): String? = additionalMetadata + + fun image(): String? = image + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): PetUploadImageParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [PetUploadImageParams]. */ + fun builder() = Builder() + } + + /** A builder for [PetUploadImageParams]. */ + class Builder internal constructor() { + + private var petId: Long? = null + private var additionalMetadata: String? = null + private var image: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(petUploadImageParams: PetUploadImageParams) = apply { + petId = petUploadImageParams.petId + additionalMetadata = petUploadImageParams.additionalMetadata + image = petUploadImageParams.image + additionalHeaders = petUploadImageParams.additionalHeaders.toBuilder() + additionalQueryParams = petUploadImageParams.additionalQueryParams.toBuilder() + } + + fun petId(petId: Long?) = apply { this.petId = petId } + + /** + * Alias for [Builder.petId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun petId(petId: Long) = petId(petId as Long?) + + /** Additional Metadata */ + fun additionalMetadata(additionalMetadata: String?) = apply { + this.additionalMetadata = additionalMetadata + } + + fun image(image: String?) = apply { this.image = image } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [PetUploadImageParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetUploadImageParams = + PetUploadImageParams( + petId, + additionalMetadata, + image, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): String? = image + + fun _pathParam(index: Int): String = + when (index) { + 0 -> petId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + additionalMetadata?.let { put("additionalMetadata", it) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUploadImageParams && + petId == other.petId && + additionalMetadata == other.additionalMetadata && + image == other.image && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(petId, additionalMetadata, image, additionalHeaders, additionalQueryParams) + + override fun toString() = + "PetUploadImageParams{petId=$petId, additionalMetadata=$additionalMetadata, image=$image, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponse.kt new file mode 100644 index 0000000..fca736b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponse.kt @@ -0,0 +1,212 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class PetUploadImageResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val code: JsonField, + private val message: JsonField, + private val type: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("code") @ExcludeMissing code: JsonField = JsonMissing.of(), + @JsonProperty("message") @ExcludeMissing message: JsonField = JsonMissing.of(), + @JsonProperty("type") @ExcludeMissing type: JsonField = JsonMissing.of(), + ) : this(code, message, type, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun code(): Int? = code.getNullable("code") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun message(): String? = message.getNullable("message") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun type(): String? = type.getNullable("type") + + /** + * Returns the raw JSON value of [code]. + * + * Unlike [code], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("code") @ExcludeMissing fun _code(): JsonField = code + + /** + * Returns the raw JSON value of [message]. + * + * Unlike [message], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message + + /** + * Returns the raw JSON value of [type]. + * + * Unlike [type], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [PetUploadImageResponse]. */ + fun builder() = Builder() + } + + /** A builder for [PetUploadImageResponse]. */ + class Builder internal constructor() { + + private var code: JsonField = JsonMissing.of() + private var message: JsonField = JsonMissing.of() + private var type: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(petUploadImageResponse: PetUploadImageResponse) = apply { + code = petUploadImageResponse.code + message = petUploadImageResponse.message + type = petUploadImageResponse.type + additionalProperties = petUploadImageResponse.additionalProperties.toMutableMap() + } + + fun code(code: Int) = code(JsonField.of(code)) + + /** + * Sets [Builder.code] to an arbitrary JSON value. + * + * You should usually call [Builder.code] with a well-typed [Int] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun code(code: JsonField) = apply { this.code = code } + + fun message(message: String) = message(JsonField.of(message)) + + /** + * Sets [Builder.message] to an arbitrary JSON value. + * + * You should usually call [Builder.message] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun message(message: JsonField) = apply { this.message = message } + + fun type(type: String) = type(JsonField.of(type)) + + /** + * Sets [Builder.type] to an arbitrary JSON value. + * + * You should usually call [Builder.type] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun type(type: JsonField) = apply { this.type = type } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [PetUploadImageResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): PetUploadImageResponse = + PetUploadImageResponse(code, message, type, additionalProperties.toMutableMap()) + } + + private var validated: Boolean = false + + fun validate(): PetUploadImageResponse = apply { + if (validated) { + return@apply + } + + code() + message() + type() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (code.asKnown() == null) 0 else 1) + + (if (message.asKnown() == null) 0 else 1) + + (if (type.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is PetUploadImageResponse && + code == other.code && + message == other.message && + type == other.type && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(code, message, type, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "PetUploadImageResponse{code=$code, message=$message, type=$type, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParams.kt new file mode 100644 index 0000000..fef124d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParams.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Returns a map of status codes to quantities */ +class StoreListInventoryParams +private constructor( + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): StoreListInventoryParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [StoreListInventoryParams]. */ + fun builder() = Builder() + } + + /** A builder for [StoreListInventoryParams]. */ + class Builder internal constructor() { + + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(storeListInventoryParams: StoreListInventoryParams) = apply { + additionalHeaders = storeListInventoryParams.additionalHeaders.toBuilder() + additionalQueryParams = storeListInventoryParams.additionalQueryParams.toBuilder() + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [StoreListInventoryParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): StoreListInventoryParams = + StoreListInventoryParams(additionalHeaders.build(), additionalQueryParams.build()) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StoreListInventoryParams && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(additionalHeaders, additionalQueryParams) + + override fun toString() = + "StoreListInventoryParams{additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponse.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponse.kt new file mode 100644 index 0000000..b2f7d96 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponse.kt @@ -0,0 +1,112 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.toImmutable +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Objects + +class StoreListInventoryResponse +@JsonCreator +private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map +) { + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = additionalProperties + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [StoreListInventoryResponse]. + */ + fun builder() = Builder() + } + + /** A builder for [StoreListInventoryResponse]. */ + class Builder internal constructor() { + + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(storeListInventoryResponse: StoreListInventoryResponse) = apply { + additionalProperties = storeListInventoryResponse.additionalProperties.toMutableMap() + } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [StoreListInventoryResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): StoreListInventoryResponse = + StoreListInventoryResponse(additionalProperties.toImmutable()) + } + + private var validated: Boolean = false + + fun validate(): StoreListInventoryResponse = apply { + if (validated) { + return@apply + } + + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is StoreListInventoryResponse && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "StoreListInventoryResponse{additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParams.kt new file mode 100644 index 0000000..c7cc400 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParams.kt @@ -0,0 +1,185 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.immutableEmptyMap +import com.pioneer_intergration_app.api.models.Order +import java.util.Objects + +/** Place a new order in the store */ +class OrderCreateParams +private constructor( + private val order: Order?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun order(): Order? = order + + fun _additionalBodyProperties(): Map = + order?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): OrderCreateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [OrderCreateParams]. */ + fun builder() = Builder() + } + + /** A builder for [OrderCreateParams]. */ + class Builder internal constructor() { + + private var order: Order? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(orderCreateParams: OrderCreateParams) = apply { + order = orderCreateParams.order + additionalHeaders = orderCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = orderCreateParams.additionalQueryParams.toBuilder() + } + + fun order(order: Order?) = apply { this.order = order } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [OrderCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OrderCreateParams = + OrderCreateParams(order, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _body(): Order? = order + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OrderCreateParams && + order == other.order && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(order, additionalHeaders, additionalQueryParams) + + override fun toString() = + "OrderCreateParams{order=$order, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParams.kt new file mode 100644 index 0000000..c38db95 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParams.kt @@ -0,0 +1,232 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will + * generate API errors + */ +class OrderDeleteParams +private constructor( + private val orderId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun orderId(): Long? = orderId + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): OrderDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [OrderDeleteParams]. */ + fun builder() = Builder() + } + + /** A builder for [OrderDeleteParams]. */ + class Builder internal constructor() { + + private var orderId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(orderDeleteParams: OrderDeleteParams) = apply { + orderId = orderDeleteParams.orderId + additionalHeaders = orderDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = orderDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = orderDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun orderId(orderId: Long?) = apply { this.orderId = orderId } + + /** + * Alias for [Builder.orderId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun orderId(orderId: Long) = orderId(orderId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [OrderDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OrderDeleteParams = + OrderDeleteParams( + orderId, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> orderId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OrderDeleteParams && + orderId == other.orderId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(orderId, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "OrderDeleteParams{orderId=$orderId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParams.kt new file mode 100644 index 0000000..591ab90 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParams.kt @@ -0,0 +1,193 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate + * exceptions. + */ +class OrderRetrieveParams +private constructor( + private val orderId: Long?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun orderId(): Long? = orderId + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): OrderRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [OrderRetrieveParams]. */ + fun builder() = Builder() + } + + /** A builder for [OrderRetrieveParams]. */ + class Builder internal constructor() { + + private var orderId: Long? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(orderRetrieveParams: OrderRetrieveParams) = apply { + orderId = orderRetrieveParams.orderId + additionalHeaders = orderRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = orderRetrieveParams.additionalQueryParams.toBuilder() + } + + fun orderId(orderId: Long?) = apply { this.orderId = orderId } + + /** + * Alias for [Builder.orderId]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun orderId(orderId: Long) = orderId(orderId as Long?) + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [OrderRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): OrderRetrieveParams = + OrderRetrieveParams(orderId, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> orderId?.toString() ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is OrderRetrieveParams && + orderId == other.orderId && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(orderId, additionalHeaders, additionalQueryParams) + + override fun toString() = + "OrderRetrieveParams{orderId=$orderId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/User.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/User.kt new file mode 100644 index 0000000..1a411b8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/User.kt @@ -0,0 +1,388 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.fasterxml.jackson.annotation.JsonAnyGetter +import com.fasterxml.jackson.annotation.JsonAnySetter +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonProperty +import com.pioneer_intergration_app.api.core.ExcludeMissing +import com.pioneer_intergration_app.api.core.JsonField +import com.pioneer_intergration_app.api.core.JsonMissing +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppInvalidDataException +import java.util.Collections +import java.util.Objects + +class User +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val id: JsonField, + private val email: JsonField, + private val firstName: JsonField, + private val lastName: JsonField, + private val password: JsonField, + private val phone: JsonField, + private val username: JsonField, + private val userStatus: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("email") @ExcludeMissing email: JsonField = JsonMissing.of(), + @JsonProperty("firstName") @ExcludeMissing firstName: JsonField = JsonMissing.of(), + @JsonProperty("lastName") @ExcludeMissing lastName: JsonField = JsonMissing.of(), + @JsonProperty("password") @ExcludeMissing password: JsonField = JsonMissing.of(), + @JsonProperty("phone") @ExcludeMissing phone: JsonField = JsonMissing.of(), + @JsonProperty("username") @ExcludeMissing username: JsonField = JsonMissing.of(), + @JsonProperty("userStatus") @ExcludeMissing userStatus: JsonField = JsonMissing.of(), + ) : this(id, email, firstName, lastName, password, phone, username, userStatus, mutableMapOf()) + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun id(): Long? = id.getNullable("id") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun email(): String? = email.getNullable("email") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun firstName(): String? = firstName.getNullable("firstName") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun lastName(): String? = lastName.getNullable("lastName") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun password(): String? = password.getNullable("password") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun phone(): String? = phone.getNullable("phone") + + /** + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun username(): String? = username.getNullable("username") + + /** + * User Status + * + * @throws PioneerIntergrationAppInvalidDataException if the JSON field has an unexpected type + * (e.g. if the server responded with an unexpected value). + */ + fun userStatus(): Int? = userStatus.getNullable("userStatus") + + /** + * Returns the raw JSON value of [id]. + * + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id + + /** + * Returns the raw JSON value of [email]. + * + * Unlike [email], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("email") @ExcludeMissing fun _email(): JsonField = email + + /** + * Returns the raw JSON value of [firstName]. + * + * Unlike [firstName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("firstName") @ExcludeMissing fun _firstName(): JsonField = firstName + + /** + * Returns the raw JSON value of [lastName]. + * + * Unlike [lastName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("lastName") @ExcludeMissing fun _lastName(): JsonField = lastName + + /** + * Returns the raw JSON value of [password]. + * + * Unlike [password], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("password") @ExcludeMissing fun _password(): JsonField = password + + /** + * Returns the raw JSON value of [phone]. + * + * Unlike [phone], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("phone") @ExcludeMissing fun _phone(): JsonField = phone + + /** + * Returns the raw JSON value of [username]. + * + * Unlike [username], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("username") @ExcludeMissing fun _username(): JsonField = username + + /** + * Returns the raw JSON value of [userStatus]. + * + * Unlike [userStatus], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("userStatus") @ExcludeMissing fun _userStatus(): JsonField = userStatus + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** Returns a mutable builder for constructing an instance of [User]. */ + fun builder() = Builder() + } + + /** A builder for [User]. */ + class Builder internal constructor() { + + private var id: JsonField = JsonMissing.of() + private var email: JsonField = JsonMissing.of() + private var firstName: JsonField = JsonMissing.of() + private var lastName: JsonField = JsonMissing.of() + private var password: JsonField = JsonMissing.of() + private var phone: JsonField = JsonMissing.of() + private var username: JsonField = JsonMissing.of() + private var userStatus: JsonField = JsonMissing.of() + private var additionalProperties: MutableMap = mutableMapOf() + + internal fun from(user: User) = apply { + id = user.id + email = user.email + firstName = user.firstName + lastName = user.lastName + password = user.password + phone = user.phone + username = user.username + userStatus = user.userStatus + additionalProperties = user.additionalProperties.toMutableMap() + } + + fun id(id: Long) = id(JsonField.of(id)) + + /** + * Sets [Builder.id] to an arbitrary JSON value. + * + * You should usually call [Builder.id] with a well-typed [Long] value instead. This method + * is primarily for setting the field to an undocumented or not yet supported value. + */ + fun id(id: JsonField) = apply { this.id = id } + + fun email(email: String) = email(JsonField.of(email)) + + /** + * Sets [Builder.email] to an arbitrary JSON value. + * + * You should usually call [Builder.email] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun email(email: JsonField) = apply { this.email = email } + + fun firstName(firstName: String) = firstName(JsonField.of(firstName)) + + /** + * Sets [Builder.firstName] to an arbitrary JSON value. + * + * You should usually call [Builder.firstName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun firstName(firstName: JsonField) = apply { this.firstName = firstName } + + fun lastName(lastName: String) = lastName(JsonField.of(lastName)) + + /** + * Sets [Builder.lastName] to an arbitrary JSON value. + * + * You should usually call [Builder.lastName] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun lastName(lastName: JsonField) = apply { this.lastName = lastName } + + fun password(password: String) = password(JsonField.of(password)) + + /** + * Sets [Builder.password] to an arbitrary JSON value. + * + * You should usually call [Builder.password] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun password(password: JsonField) = apply { this.password = password } + + fun phone(phone: String) = phone(JsonField.of(phone)) + + /** + * Sets [Builder.phone] to an arbitrary JSON value. + * + * You should usually call [Builder.phone] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun phone(phone: JsonField) = apply { this.phone = phone } + + fun username(username: String) = username(JsonField.of(username)) + + /** + * Sets [Builder.username] to an arbitrary JSON value. + * + * You should usually call [Builder.username] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun username(username: JsonField) = apply { this.username = username } + + /** User Status */ + fun userStatus(userStatus: Int) = userStatus(JsonField.of(userStatus)) + + /** + * Sets [Builder.userStatus] to an arbitrary JSON value. + * + * You should usually call [Builder.userStatus] with a well-typed [Int] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun userStatus(userStatus: JsonField) = apply { this.userStatus = userStatus } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [User]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): User = + User( + id, + email, + firstName, + lastName, + password, + phone, + username, + userStatus, + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + fun validate(): User = apply { + if (validated) { + return@apply + } + + id() + email() + firstName() + lastName() + password() + phone() + username() + userStatus() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: PioneerIntergrationAppInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + internal fun validity(): Int = + (if (id.asKnown() == null) 0 else 1) + + (if (email.asKnown() == null) 0 else 1) + + (if (firstName.asKnown() == null) 0 else 1) + + (if (lastName.asKnown() == null) 0 else 1) + + (if (password.asKnown() == null) 0 else 1) + + (if (phone.asKnown() == null) 0 else 1) + + (if (username.asKnown() == null) 0 else 1) + + (if (userStatus.asKnown() == null) 0 else 1) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is User && + id == other.id && + email == other.email && + firstName == other.firstName && + lastName == other.lastName && + password == other.password && + phone == other.phone && + username == other.username && + userStatus == other.userStatus && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash( + id, + email, + firstName, + lastName, + password, + phone, + username, + userStatus, + additionalProperties, + ) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "User{id=$id, email=$email, firstName=$firstName, lastName=$lastName, password=$password, phone=$phone, username=$username, userStatus=$userStatus, additionalProperties=$additionalProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParams.kt new file mode 100644 index 0000000..4bf2c4b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParams.kt @@ -0,0 +1,184 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.immutableEmptyMap +import java.util.Objects + +/** This can only be done by the logged in user. */ +class UserCreateParams +private constructor( + private val user: User?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun user(): User? = user + + fun _additionalBodyProperties(): Map = + user?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserCreateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserCreateParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserCreateParams]. */ + class Builder internal constructor() { + + private var user: User? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userCreateParams: UserCreateParams) = apply { + user = userCreateParams.user + additionalHeaders = userCreateParams.additionalHeaders.toBuilder() + additionalQueryParams = userCreateParams.additionalQueryParams.toBuilder() + } + + fun user(user: User?) = apply { this.user = user } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserCreateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserCreateParams = + UserCreateParams(user, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _body(): User? = user + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserCreateParams && + user == other.user && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(user, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserCreateParams{user=$user, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParams.kt new file mode 100644 index 0000000..391fbb3 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParams.kt @@ -0,0 +1,191 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** Creates list of users with given input array */ +class UserCreateWithListParams +private constructor( + private val items: List?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun items(): List? = items + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserCreateWithListParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserCreateWithListParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserCreateWithListParams]. */ + class Builder internal constructor() { + + private var items: MutableList? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userCreateWithListParams: UserCreateWithListParams) = apply { + items = userCreateWithListParams.items?.toMutableList() + additionalHeaders = userCreateWithListParams.additionalHeaders.toBuilder() + additionalQueryParams = userCreateWithListParams.additionalQueryParams.toBuilder() + } + + fun items(items: List?) = apply { this.items = items?.toMutableList() } + + /** + * Adds a single [User] to [items]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addItem(item: User) = apply { items = (items ?: mutableListOf()).apply { add(item) } } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserCreateWithListParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserCreateWithListParams = + UserCreateWithListParams( + items?.toImmutable(), + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): List? = items + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserCreateWithListParams && + items == other.items && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(items, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserCreateWithListParams{items=$items, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParams.kt new file mode 100644 index 0000000..6a4b771 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParams.kt @@ -0,0 +1,222 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.toImmutable +import java.util.Objects + +/** This can only be done by the logged in user. */ +class UserDeleteParams +private constructor( + private val username: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, + private val additionalBodyProperties: Map, +) : Params { + + fun username(): String? = username + + /** Additional body properties to send with the request. */ + fun _additionalBodyProperties(): Map = additionalBodyProperties + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserDeleteParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserDeleteParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserDeleteParams]. */ + class Builder internal constructor() { + + private var username: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + private var additionalBodyProperties: MutableMap = mutableMapOf() + + internal fun from(userDeleteParams: UserDeleteParams) = apply { + username = userDeleteParams.username + additionalHeaders = userDeleteParams.additionalHeaders.toBuilder() + additionalQueryParams = userDeleteParams.additionalQueryParams.toBuilder() + additionalBodyProperties = userDeleteParams.additionalBodyProperties.toMutableMap() + } + + fun username(username: String?) = apply { this.username = username } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + this.additionalBodyProperties.clear() + putAllAdditionalBodyProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + additionalBodyProperties.put(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + this.additionalBodyProperties.putAll(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { + additionalBodyProperties.remove(key) + } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalBodyProperty) + } + + /** + * Returns an immutable instance of [UserDeleteParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserDeleteParams = + UserDeleteParams( + username, + additionalHeaders.build(), + additionalQueryParams.build(), + additionalBodyProperties.toImmutable(), + ) + } + + fun _body(): Map? = additionalBodyProperties.ifEmpty { null } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> username ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserDeleteParams && + username == other.username && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams && + additionalBodyProperties == other.additionalBodyProperties + } + + override fun hashCode(): Int = + Objects.hash(username, additionalHeaders, additionalQueryParams, additionalBodyProperties) + + override fun toString() = + "UserDeleteParams{username=$username, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams, additionalBodyProperties=$additionalBodyProperties}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParams.kt new file mode 100644 index 0000000..f4c3abb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParams.kt @@ -0,0 +1,202 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Logs user into the system */ +class UserLoginParams +private constructor( + private val password: String?, + private val username: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** The password for login in clear text */ + fun password(): String? = password + + /** The user name for login */ + fun username(): String? = username + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserLoginParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserLoginParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserLoginParams]. */ + class Builder internal constructor() { + + private var password: String? = null + private var username: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userLoginParams: UserLoginParams) = apply { + password = userLoginParams.password + username = userLoginParams.username + additionalHeaders = userLoginParams.additionalHeaders.toBuilder() + additionalQueryParams = userLoginParams.additionalQueryParams.toBuilder() + } + + /** The password for login in clear text */ + fun password(password: String?) = apply { this.password = password } + + /** The user name for login */ + fun username(username: String?) = apply { this.username = username } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserLoginParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserLoginParams = + UserLoginParams( + password, + username, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = + QueryParams.builder() + .apply { + password?.let { put("password", it) } + username?.let { put("username", it) } + putAll(additionalQueryParams) + } + .build() + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserLoginParams && + password == other.password && + username == other.username && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(password, username, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserLoginParams{password=$password, username=$username, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParams.kt new file mode 100644 index 0000000..23b884c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParams.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Logs out current logged in user session */ +class UserLogoutParams +private constructor( + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserLogoutParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserLogoutParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserLogoutParams]. */ + class Builder internal constructor() { + + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userLogoutParams: UserLogoutParams) = apply { + additionalHeaders = userLogoutParams.additionalHeaders.toBuilder() + additionalQueryParams = userLogoutParams.additionalQueryParams.toBuilder() + } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserLogoutParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserLogoutParams = + UserLogoutParams(additionalHeaders.build(), additionalQueryParams.build()) + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserLogoutParams && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserLogoutParams{additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParams.kt new file mode 100644 index 0000000..6e6d293 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParams.kt @@ -0,0 +1,183 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import java.util.Objects + +/** Get user by user name */ +class UserRetrieveParams +private constructor( + private val username: String?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun username(): String? = username + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserRetrieveParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserRetrieveParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserRetrieveParams]. */ + class Builder internal constructor() { + + private var username: String? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userRetrieveParams: UserRetrieveParams) = apply { + username = userRetrieveParams.username + additionalHeaders = userRetrieveParams.additionalHeaders.toBuilder() + additionalQueryParams = userRetrieveParams.additionalQueryParams.toBuilder() + } + + fun username(username: String?) = apply { this.username = username } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserRetrieveParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserRetrieveParams = + UserRetrieveParams(username, additionalHeaders.build(), additionalQueryParams.build()) + } + + fun _pathParam(index: Int): String = + when (index) { + 0 -> username ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserRetrieveParams && + username == other.username && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = Objects.hash(username, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserRetrieveParams{username=$username, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParams.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParams.kt new file mode 100644 index 0000000..d4d6199 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParams.kt @@ -0,0 +1,206 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.Params +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.http.QueryParams +import com.pioneer_intergration_app.api.core.immutableEmptyMap +import java.util.Objects + +/** This can only be done by the logged in user. */ +class UserUpdateParams +private constructor( + private val existingUsername: String?, + private val user: User?, + private val additionalHeaders: Headers, + private val additionalQueryParams: QueryParams, +) : Params { + + fun existingUsername(): String? = existingUsername + + fun user(): User? = user + + fun _additionalBodyProperties(): Map = + user?._additionalProperties() ?: immutableEmptyMap() + + /** Additional headers to send with the request. */ + fun _additionalHeaders(): Headers = additionalHeaders + + /** Additional query param to send with the request. */ + fun _additionalQueryParams(): QueryParams = additionalQueryParams + + fun toBuilder() = Builder().from(this) + + companion object { + + fun none(): UserUpdateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [UserUpdateParams]. */ + fun builder() = Builder() + } + + /** A builder for [UserUpdateParams]. */ + class Builder internal constructor() { + + private var existingUsername: String? = null + private var user: User? = null + private var additionalHeaders: Headers.Builder = Headers.builder() + private var additionalQueryParams: QueryParams.Builder = QueryParams.builder() + + internal fun from(userUpdateParams: UserUpdateParams) = apply { + existingUsername = userUpdateParams.existingUsername + user = userUpdateParams.user + additionalHeaders = userUpdateParams.additionalHeaders.toBuilder() + additionalQueryParams = userUpdateParams.additionalQueryParams.toBuilder() + } + + fun existingUsername(existingUsername: String?) = apply { + this.existingUsername = existingUsername + } + + fun user(user: User?) = apply { this.user = user } + + fun additionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun additionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.clear() + putAllAdditionalHeaders(additionalHeaders) + } + + fun putAdditionalHeader(name: String, value: String) = apply { + additionalHeaders.put(name, value) + } + + fun putAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.put(name, values) + } + + fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.putAll(additionalHeaders) + } + + fun replaceAdditionalHeaders(name: String, value: String) = apply { + additionalHeaders.replace(name, value) + } + + fun replaceAdditionalHeaders(name: String, values: Iterable) = apply { + additionalHeaders.replace(name, values) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply { + this.additionalHeaders.replaceAll(additionalHeaders) + } + + fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) } + + fun removeAllAdditionalHeaders(names: Set) = apply { + additionalHeaders.removeAll(names) + } + + fun additionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun additionalQueryParams(additionalQueryParams: Map>) = apply { + this.additionalQueryParams.clear() + putAllAdditionalQueryParams(additionalQueryParams) + } + + fun putAdditionalQueryParam(key: String, value: String) = apply { + additionalQueryParams.put(key, value) + } + + fun putAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.put(key, values) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun putAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.putAll(additionalQueryParams) + } + + fun replaceAdditionalQueryParams(key: String, value: String) = apply { + additionalQueryParams.replace(key, value) + } + + fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply { + additionalQueryParams.replace(key, values) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) = + apply { + this.additionalQueryParams.replaceAll(additionalQueryParams) + } + + fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) } + + fun removeAllAdditionalQueryParams(keys: Set) = apply { + additionalQueryParams.removeAll(keys) + } + + /** + * Returns an immutable instance of [UserUpdateParams]. + * + * Further updates to this [Builder] will not mutate the returned instance. + */ + fun build(): UserUpdateParams = + UserUpdateParams( + existingUsername, + user, + additionalHeaders.build(), + additionalQueryParams.build(), + ) + } + + fun _body(): User? = user + + fun _pathParam(index: Int): String = + when (index) { + 0 -> existingUsername ?: "" + else -> "" + } + + override fun _headers(): Headers = additionalHeaders + + override fun _queryParams(): QueryParams = additionalQueryParams + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is UserUpdateParams && + existingUsername == other.existingUsername && + user == other.user && + additionalHeaders == other.additionalHeaders && + additionalQueryParams == other.additionalQueryParams + } + + override fun hashCode(): Int = + Objects.hash(existingUsername, user, additionalHeaders, additionalQueryParams) + + override fun toString() = + "UserUpdateParams{existingUsername=$existingUsername, user=$user, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}" +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsync.kt new file mode 100644 index 0000000..3839b7d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsync.kt @@ -0,0 +1,323 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +interface PetServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetServiceAsync + + /** Add a new pet to the store */ + suspend fun create( + params: PetCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see create */ + suspend fun create(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** Returns a single pet */ + suspend fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + suspend fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see retrieve */ + suspend fun retrieve(petId: Long, requestOptions: RequestOptions): Pet = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** Update an existing pet by Id */ + suspend fun update( + params: PetUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see update */ + suspend fun update(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** delete a pet */ + suspend fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + suspend fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see delete */ + suspend fun delete(petId: Long, requestOptions: RequestOptions) = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** Multiple status values can be provided with comma separated strings */ + suspend fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByStatus */ + suspend fun findByStatus(requestOptions: RequestOptions): List = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + */ + suspend fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByTags */ + suspend fun findByTags(requestOptions: RequestOptions): List = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** Updates a pet in the store with form data */ + suspend fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + suspend fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see updateById */ + suspend fun updateById(petId: Long, requestOptions: RequestOptions) = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** uploads an image */ + suspend fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse + + /** @see uploadImage */ + suspend fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + + /** A view of [PetServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /pet`, but is otherwise the same as + * [PetServiceAsync.create]. + */ + @MustBeClosed + suspend fun create( + params: PetCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + suspend fun create( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/{petId}`, but is otherwise the same as + * [PetServiceAsync.retrieve]. + */ + @MustBeClosed + suspend fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve(petId: Long, requestOptions: RequestOptions): HttpResponseFor = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /pet`, but is otherwise the same as + * [PetServiceAsync.update]. + */ + @MustBeClosed + suspend fun update( + params: PetUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see update */ + @MustBeClosed + suspend fun update( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /pet/{petId}`, but is otherwise the same as + * [PetServiceAsync.delete]. + */ + @MustBeClosed + suspend fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + suspend fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + suspend fun delete(petId: Long, requestOptions: RequestOptions): HttpResponse = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByStatus`, but is otherwise the same as + * [PetServiceAsync.findByStatus]. + */ + @MustBeClosed + suspend fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByStatus */ + @MustBeClosed + suspend fun findByStatus(requestOptions: RequestOptions): HttpResponseFor> = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByTags`, but is otherwise the same as + * [PetServiceAsync.findByTags]. + */ + @MustBeClosed + suspend fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByTags */ + @MustBeClosed + suspend fun findByTags(requestOptions: RequestOptions): HttpResponseFor> = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}`, but is otherwise the same as + * [PetServiceAsync.updateById]. + */ + @MustBeClosed + suspend fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + @MustBeClosed + suspend fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see updateById */ + @MustBeClosed + suspend fun updateById(petId: Long, requestOptions: RequestOptions): HttpResponse = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}/uploadImage`, but is otherwise the + * same as [PetServiceAsync.uploadImage]. + */ + @MustBeClosed + suspend fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + @MustBeClosed + suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see uploadImage */ + @MustBeClosed + suspend fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncImpl.kt new file mode 100644 index 0000000..4ff6ca2 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncImpl.kt @@ -0,0 +1,316 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +class PetServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + PetServiceAsync { + + private val withRawResponse: PetServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): PetServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetServiceAsync = + PetServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override suspend fun create(params: PetCreateParams, requestOptions: RequestOptions): Pet = + // post /pet + withRawResponse().create(params, requestOptions).parse() + + override suspend fun retrieve(params: PetRetrieveParams, requestOptions: RequestOptions): Pet = + // get /pet/{petId} + withRawResponse().retrieve(params, requestOptions).parse() + + override suspend fun update(params: PetUpdateParams, requestOptions: RequestOptions): Pet = + // put /pet + withRawResponse().update(params, requestOptions).parse() + + override suspend fun delete(params: PetDeleteParams, requestOptions: RequestOptions) { + // delete /pet/{petId} + withRawResponse().delete(params, requestOptions) + } + + override suspend fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByStatus + withRawResponse().findByStatus(params, requestOptions).parse() + + override suspend fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByTags + withRawResponse().findByTags(params, requestOptions).parse() + + override suspend fun updateById(params: PetUpdateByIdParams, requestOptions: RequestOptions) { + // post /pet/{petId} + withRawResponse().updateById(params, requestOptions) + } + + override suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + // post /pet/{petId}/uploadImage + withRawResponse().uploadImage(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PetServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PetServiceAsync.WithRawResponse = + PetServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun create( + params: PetCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun update( + params: PetUpdateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { updateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override suspend fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val findByStatusHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override suspend fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByStatus") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByStatusHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val findByTagsHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override suspend fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByTags") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByTagsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val updateByIdHandler: Handler = emptyHandler() + + override suspend fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateByIdHandler.handle(it) } + } + } + + private val uploadImageHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override suspend fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + checkRequired("image", params._body()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0), "uploadImage") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { uploadImageHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsync.kt new file mode 100644 index 0000000..96ae910 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsync.kt @@ -0,0 +1,70 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.async.store.OrderServiceAsync + +interface StoreServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreServiceAsync + + fun orders(): OrderServiceAsync + + /** Returns a map of status codes to quantities */ + suspend fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): StoreListInventoryResponse + + /** @see listInventory */ + suspend fun listInventory(requestOptions: RequestOptions): StoreListInventoryResponse = + listInventory(StoreListInventoryParams.none(), requestOptions) + + /** A view of [StoreServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): StoreServiceAsync.WithRawResponse + + fun orders(): OrderServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `get /store/inventory`, but is otherwise the same as + * [StoreServiceAsync.listInventory]. + */ + @MustBeClosed + suspend fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see listInventory */ + @MustBeClosed + suspend fun listInventory( + requestOptions: RequestOptions + ): HttpResponseFor = + listInventory(StoreListInventoryParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncImpl.kt new file mode 100644 index 0000000..a6b22cb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncImpl.kt @@ -0,0 +1,91 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.async.store.OrderServiceAsync +import com.pioneer_intergration_app.api.services.async.store.OrderServiceAsyncImpl + +class StoreServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + StoreServiceAsync { + + private val withRawResponse: StoreServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val orders: OrderServiceAsync by lazy { OrderServiceAsyncImpl(clientOptions) } + + override fun withRawResponse(): StoreServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreServiceAsync = + StoreServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun orders(): OrderServiceAsync = orders + + override suspend fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): StoreListInventoryResponse = + // get /store/inventory + withRawResponse().listInventory(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + StoreServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + private val orders: OrderServiceAsync.WithRawResponse by lazy { + OrderServiceAsyncImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): StoreServiceAsync.WithRawResponse = + StoreServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + override fun orders(): OrderServiceAsync.WithRawResponse = orders + + private val listInventoryHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override suspend fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "inventory") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listInventoryHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsync.kt new file mode 100644 index 0000000..1e7fb40 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsync.kt @@ -0,0 +1,279 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +interface UserServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserServiceAsync + + /** This can only be done by the logged in user. */ + suspend fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see create */ + suspend fun create(user: User, requestOptions: RequestOptions = RequestOptions.none()): User = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + suspend fun create(requestOptions: RequestOptions): User = + create(UserCreateParams.none(), requestOptions) + + /** Get user by user name */ + suspend fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User = retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see retrieve */ + suspend fun retrieve(username: String, requestOptions: RequestOptions): User = + retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + suspend fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + suspend fun update( + params: UserUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see update */ + suspend fun update(existingUsername: String, requestOptions: RequestOptions) = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + suspend fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + suspend fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see delete */ + suspend fun delete(username: String, requestOptions: RequestOptions) = + delete(username, UserDeleteParams.none(), requestOptions) + + /** Creates list of users with given input array */ + suspend fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see createWithList */ + suspend fun createWithList(requestOptions: RequestOptions): User = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** Logs user into the system */ + suspend fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): String + + /** @see login */ + suspend fun login(requestOptions: RequestOptions): String = + login(UserLoginParams.none(), requestOptions) + + /** Logs out current logged in user session */ + suspend fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see logout */ + suspend fun logout(requestOptions: RequestOptions) = + logout(UserLogoutParams.none(), requestOptions) + + /** A view of [UserServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /user`, but is otherwise the same as + * [UserServiceAsync.create]. + */ + @MustBeClosed + suspend fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + suspend fun create( + user: User, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + @MustBeClosed + suspend fun create(requestOptions: RequestOptions): HttpResponseFor = + create(UserCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/{username}`, but is otherwise the same as + * [UserServiceAsync.retrieve]. + */ + @MustBeClosed + suspend fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + username: String, + requestOptions: RequestOptions, + ): HttpResponseFor = retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /user/{username}`, but is otherwise the same as + * [UserServiceAsync.update]. + */ + @MustBeClosed + suspend fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = + update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + @MustBeClosed + suspend fun update( + params: UserUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see update */ + @MustBeClosed + suspend fun update(existingUsername: String, requestOptions: RequestOptions): HttpResponse = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /user/{username}`, but is otherwise the same as + * [UserServiceAsync.delete]. + */ + @MustBeClosed + suspend fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + suspend fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + suspend fun delete(username: String, requestOptions: RequestOptions): HttpResponse = + delete(username, UserDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /user/createWithList`, but is otherwise the same as + * [UserServiceAsync.createWithList]. + */ + @MustBeClosed + suspend fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see createWithList */ + @MustBeClosed + suspend fun createWithList(requestOptions: RequestOptions): HttpResponseFor = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/login`, but is otherwise the same as + * [UserServiceAsync.login]. + */ + @MustBeClosed + suspend fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see login */ + @MustBeClosed + suspend fun login(requestOptions: RequestOptions): HttpResponseFor = + login(UserLoginParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/logout`, but is otherwise the same as + * [UserServiceAsync.logout]. + */ + @MustBeClosed + suspend fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see logout */ + @MustBeClosed + suspend fun logout(requestOptions: RequestOptions): HttpResponse = + logout(UserLogoutParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncImpl.kt new file mode 100644 index 0000000..3fbb60e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncImpl.kt @@ -0,0 +1,264 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.handlers.stringHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +class UserServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + UserServiceAsync { + + private val withRawResponse: UserServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): UserServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserServiceAsync = + UserServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override suspend fun create(params: UserCreateParams, requestOptions: RequestOptions): User = + // post /user + withRawResponse().create(params, requestOptions).parse() + + override suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions, + ): User = + // get /user/{username} + withRawResponse().retrieve(params, requestOptions).parse() + + override suspend fun update(params: UserUpdateParams, requestOptions: RequestOptions) { + // put /user/{username} + withRawResponse().update(params, requestOptions) + } + + override suspend fun delete(params: UserDeleteParams, requestOptions: RequestOptions) { + // delete /user/{username} + withRawResponse().delete(params, requestOptions) + } + + override suspend fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): User = + // post /user/createWithList + withRawResponse().createWithList(params, requestOptions).parse() + + override suspend fun login(params: UserLoginParams, requestOptions: RequestOptions): String = + // get /user/login + withRawResponse().login(params, requestOptions).parse() + + override suspend fun logout(params: UserLogoutParams, requestOptions: RequestOptions) { + // get /user/logout + withRawResponse().logout(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + UserServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): UserServiceAsync.WithRawResponse = + UserServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun create( + params: UserCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = emptyHandler() + + override suspend fun update( + params: UserUpdateParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("existingUsername", params.existingUsername()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateHandler.handle(it) } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override suspend fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val createWithListHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override suspend fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "createWithList") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createWithListHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val loginHandler: Handler = stringHandler() + + override suspend fun login( + params: UserLoginParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "login") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { loginHandler.handle(it) } + } + } + + private val logoutHandler: Handler = emptyHandler() + + override suspend fun logout( + params: UserLogoutParams, + requestOptions: RequestOptions, + ): HttpResponse { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "logout") + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { logoutHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsync.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsync.kt new file mode 100644 index 0000000..e1ef420 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsync.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async.store + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +interface OrderServiceAsync { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderServiceAsync + + /** Place a new order in the store */ + suspend fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see create */ + suspend fun create( + order: Order, + requestOptions: RequestOptions = RequestOptions.none(), + ): Order = create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + suspend fun create(requestOptions: RequestOptions): Order = + create(OrderCreateParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate + * exceptions. + */ + suspend fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order = retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see retrieve */ + suspend fun retrieve(orderId: Long, requestOptions: RequestOptions): Order = + retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will + * generate API errors + */ + suspend fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + suspend fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see delete */ + suspend fun delete(orderId: Long, requestOptions: RequestOptions) = + delete(orderId, OrderDeleteParams.none(), requestOptions) + + /** A view of [OrderServiceAsync] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): OrderServiceAsync.WithRawResponse + + /** + * Returns a raw HTTP response for `post /store/order`, but is otherwise the same as + * [OrderServiceAsync.create]. + */ + @MustBeClosed + suspend fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + suspend fun create( + order: Order, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + @MustBeClosed + suspend fun create(requestOptions: RequestOptions): HttpResponseFor = + create(OrderCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /store/order/{orderId}`, but is otherwise the same + * as [OrderServiceAsync.retrieve]. + */ + @MustBeClosed + suspend fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + suspend fun retrieve( + orderId: Long, + requestOptions: RequestOptions, + ): HttpResponseFor = retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /store/order/{orderId}`, but is otherwise the + * same as [OrderServiceAsync.delete]. + */ + @MustBeClosed + suspend fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + suspend fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + suspend fun delete(orderId: Long, requestOptions: RequestOptions): HttpResponse = + delete(orderId, OrderDeleteParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncImpl.kt new file mode 100644 index 0000000..dd039f4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncImpl.kt @@ -0,0 +1,146 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async.store + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepareAsync +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +class OrderServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : + OrderServiceAsync { + + private val withRawResponse: OrderServiceAsync.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): OrderServiceAsync.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderServiceAsync = + OrderServiceAsyncImpl(clientOptions.toBuilder().apply(modifier).build()) + + override suspend fun create(params: OrderCreateParams, requestOptions: RequestOptions): Order = + // post /store/order + withRawResponse().create(params, requestOptions).parse() + + override suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions, + ): Order = + // get /store/order/{orderId} + withRawResponse().retrieve(params, requestOptions).parse() + + override suspend fun delete(params: OrderDeleteParams, requestOptions: RequestOptions) { + // delete /store/order/{orderId} + withRawResponse().delete(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + OrderServiceAsync.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): OrderServiceAsync.WithRawResponse = + OrderServiceAsyncImpl.WithRawResponseImpl( + clientOptions.toBuilder().apply(modifier).build() + ) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun create( + params: OrderCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override suspend fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override suspend fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepareAsync(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.executeAsync(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetService.kt new file mode 100644 index 0000000..9dabb5b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetService.kt @@ -0,0 +1,314 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +interface PetService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetService + + /** Add a new pet to the store */ + fun create(params: PetCreateParams, requestOptions: RequestOptions = RequestOptions.none()): Pet + + /** @see create */ + fun create(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** Returns a single pet */ + fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Pet + + /** @see retrieve */ + fun retrieve(petId: Long, requestOptions: RequestOptions): Pet = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** Update an existing pet by Id */ + fun update(params: PetUpdateParams, requestOptions: RequestOptions = RequestOptions.none()): Pet + + /** @see update */ + fun update(pet: Pet, requestOptions: RequestOptions = RequestOptions.none()): Pet = + update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** delete a pet */ + fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + fun delete(params: PetDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see delete */ + fun delete(petId: Long, requestOptions: RequestOptions) = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** Multiple status values can be provided with comma separated strings */ + fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByStatus */ + fun findByStatus(requestOptions: RequestOptions): List = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + */ + fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): List + + /** @see findByTags */ + fun findByTags(requestOptions: RequestOptions): List = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** Updates a pet in the store with form data */ + fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see updateById */ + fun updateById(petId: Long, requestOptions: RequestOptions) = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** uploads an image */ + fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): PetUploadImageResponse + + /** @see uploadImage */ + fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + + /** A view of [PetService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /pet`, but is otherwise the same as + * [PetService.create]. + */ + @MustBeClosed + fun create( + params: PetCreateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = create(PetCreateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/{petId}`, but is otherwise the same as + * [PetService.retrieve]. + */ + @MustBeClosed + fun retrieve( + petId: Long, + params: PetRetrieveParams = PetRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = retrieve(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(petId: Long, requestOptions: RequestOptions): HttpResponseFor = + retrieve(petId, PetRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /pet`, but is otherwise the same as + * [PetService.update]. + */ + @MustBeClosed + fun update( + params: PetUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see update */ + @MustBeClosed + fun update( + pet: Pet, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = update(PetUpdateParams.builder().pet(pet).build(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /pet/{petId}`, but is otherwise the same as + * [PetService.delete]. + */ + @MustBeClosed + fun delete( + petId: Long, + params: PetDeleteParams = PetDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + params: PetDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + fun delete(petId: Long, requestOptions: RequestOptions): HttpResponse = + delete(petId, PetDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByStatus`, but is otherwise the same as + * [PetService.findByStatus]. + */ + @MustBeClosed + fun findByStatus( + params: PetFindByStatusParams = PetFindByStatusParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByStatus */ + @MustBeClosed + fun findByStatus(requestOptions: RequestOptions): HttpResponseFor> = + findByStatus(PetFindByStatusParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /pet/findByTags`, but is otherwise the same as + * [PetService.findByTags]. + */ + @MustBeClosed + fun findByTags( + params: PetFindByTagsParams = PetFindByTagsParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor> + + /** @see findByTags */ + @MustBeClosed + fun findByTags(requestOptions: RequestOptions): HttpResponseFor> = + findByTags(PetFindByTagsParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}`, but is otherwise the same as + * [PetService.updateById]. + */ + @MustBeClosed + fun updateById( + petId: Long, + params: PetUpdateByIdParams = PetUpdateByIdParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = updateById(params.toBuilder().petId(petId).build(), requestOptions) + + /** @see updateById */ + @MustBeClosed + fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see updateById */ + @MustBeClosed + fun updateById(petId: Long, requestOptions: RequestOptions): HttpResponse = + updateById(petId, PetUpdateByIdParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /pet/{petId}/uploadImage`, but is otherwise the + * same as [PetService.uploadImage]. + */ + @MustBeClosed + fun uploadImage( + petId: Long, + image: String, + params: PetUploadImageParams = PetUploadImageParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + uploadImage(params.toBuilder().petId(petId).image(image).build(), requestOptions) + + /** @see uploadImage */ + @MustBeClosed + fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see uploadImage */ + @MustBeClosed + fun uploadImage( + petId: Long, + image: String, + requestOptions: RequestOptions, + ): HttpResponseFor = + uploadImage(petId, image, PetUploadImageParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceImpl.kt new file mode 100644 index 0000000..0fe1c4f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceImpl.kt @@ -0,0 +1,310 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetCreateParams +import com.pioneer_intergration_app.api.models.pets.PetDeleteParams +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetRetrieveParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageResponse + +class PetServiceImpl internal constructor(private val clientOptions: ClientOptions) : PetService { + + private val withRawResponse: PetService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): PetService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): PetService = + PetServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun create(params: PetCreateParams, requestOptions: RequestOptions): Pet = + // post /pet + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve(params: PetRetrieveParams, requestOptions: RequestOptions): Pet = + // get /pet/{petId} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun update(params: PetUpdateParams, requestOptions: RequestOptions): Pet = + // put /pet + withRawResponse().update(params, requestOptions).parse() + + override fun delete(params: PetDeleteParams, requestOptions: RequestOptions) { + // delete /pet/{petId} + withRawResponse().delete(params, requestOptions) + } + + override fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByStatus + withRawResponse().findByStatus(params, requestOptions).parse() + + override fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): List = + // get /pet/findByTags + withRawResponse().findByTags(params, requestOptions).parse() + + override fun updateById(params: PetUpdateByIdParams, requestOptions: RequestOptions) { + // post /pet/{petId} + withRawResponse().updateById(params, requestOptions) + } + + override fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): PetUploadImageResponse = + // post /pet/{petId}/uploadImage + withRawResponse().uploadImage(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + PetService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): PetService.WithRawResponse = + PetServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: PetCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: PetRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun update( + params: PetUpdateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet") + .body(json(clientOptions.jsonMapper, params._body())) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { updateHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override fun delete(params: PetDeleteParams, requestOptions: RequestOptions): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val findByStatusHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override fun findByStatus( + params: PetFindByStatusParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByStatus") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByStatusHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val findByTagsHandler: Handler> = + jsonHandler>(clientOptions.jsonMapper) + + override fun findByTags( + params: PetFindByTagsParams, + requestOptions: RequestOptions, + ): HttpResponseFor> { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", "findByTags") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { findByTagsHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.forEach { it.validate() } + } + } + } + } + + private val updateByIdHandler: Handler = emptyHandler() + + override fun updateById( + params: PetUpdateByIdParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateByIdHandler.handle(it) } + } + } + + private val uploadImageHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun uploadImage( + params: PetUploadImageParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("petId", params.petId()) + checkRequired("image", params._body()) + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("pet", params._pathParam(0), "uploadImage") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { uploadImageHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreService.kt new file mode 100644 index 0000000..cb479a2 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreService.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.blocking.store.OrderService + +interface StoreService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreService + + fun orders(): OrderService + + /** Returns a map of status codes to quantities */ + fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): StoreListInventoryResponse + + /** @see listInventory */ + fun listInventory(requestOptions: RequestOptions): StoreListInventoryResponse = + listInventory(StoreListInventoryParams.none(), requestOptions) + + /** A view of [StoreService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreService.WithRawResponse + + fun orders(): OrderService.WithRawResponse + + /** + * Returns a raw HTTP response for `get /store/inventory`, but is otherwise the same as + * [StoreService.listInventory]. + */ + @MustBeClosed + fun listInventory( + params: StoreListInventoryParams = StoreListInventoryParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see listInventory */ + @MustBeClosed + fun listInventory( + requestOptions: RequestOptions + ): HttpResponseFor = + listInventory(StoreListInventoryParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceImpl.kt new file mode 100644 index 0000000..54334c8 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceImpl.kt @@ -0,0 +1,89 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.StoreListInventoryResponse +import com.pioneer_intergration_app.api.services.blocking.store.OrderService +import com.pioneer_intergration_app.api.services.blocking.store.OrderServiceImpl + +class StoreServiceImpl internal constructor(private val clientOptions: ClientOptions) : + StoreService { + + private val withRawResponse: StoreService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + private val orders: OrderService by lazy { OrderServiceImpl(clientOptions) } + + override fun withRawResponse(): StoreService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): StoreService = + StoreServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun orders(): OrderService = orders + + override fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): StoreListInventoryResponse = + // get /store/inventory + withRawResponse().listInventory(params, requestOptions).parse() + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + StoreService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + private val orders: OrderService.WithRawResponse by lazy { + OrderServiceImpl.WithRawResponseImpl(clientOptions) + } + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): StoreService.WithRawResponse = + StoreServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun orders(): OrderService.WithRawResponse = orders + + private val listInventoryHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun listInventory( + params: StoreListInventoryParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "inventory") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { listInventoryHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserService.kt new file mode 100644 index 0000000..fed3a18 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserService.kt @@ -0,0 +1,270 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +interface UserService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserService + + /** This can only be done by the logged in user. */ + fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see create */ + fun create(user: User, requestOptions: RequestOptions = RequestOptions.none()): User = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + fun create(requestOptions: RequestOptions): User = + create(UserCreateParams.none(), requestOptions) + + /** Get user by user name */ + fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User = retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see retrieve */ + fun retrieve(username: String, requestOptions: RequestOptions): User = + retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + fun update(params: UserUpdateParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see update */ + fun update(existingUsername: String, requestOptions: RequestOptions) = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** This can only be done by the logged in user. */ + fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + fun delete(params: UserDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see delete */ + fun delete(username: String, requestOptions: RequestOptions) = + delete(username, UserDeleteParams.none(), requestOptions) + + /** Creates list of users with given input array */ + fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): User + + /** @see createWithList */ + fun createWithList(requestOptions: RequestOptions): User = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** Logs user into the system */ + fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): String + + /** @see login */ + fun login(requestOptions: RequestOptions): String = + login(UserLoginParams.none(), requestOptions) + + /** Logs out current logged in user session */ + fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) + + /** @see logout */ + fun logout(requestOptions: RequestOptions) = logout(UserLogoutParams.none(), requestOptions) + + /** A view of [UserService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /user`, but is otherwise the same as + * [UserService.create]. + */ + @MustBeClosed + fun create( + params: UserCreateParams = UserCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + user: User, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(UserCreateParams.builder().user(user).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create(requestOptions: RequestOptions): HttpResponseFor = + create(UserCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/{username}`, but is otherwise the same as + * [UserService.retrieve]. + */ + @MustBeClosed + fun retrieve( + username: String, + params: UserRetrieveParams = UserRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().username(username).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(username: String, requestOptions: RequestOptions): HttpResponseFor = + retrieve(username, UserRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `put /user/{username}`, but is otherwise the same as + * [UserService.update]. + */ + @MustBeClosed + fun update( + existingUsername: String, + params: UserUpdateParams = UserUpdateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = + update(params.toBuilder().existingUsername(existingUsername).build(), requestOptions) + + /** @see update */ + @MustBeClosed + fun update( + params: UserUpdateParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see update */ + @MustBeClosed + fun update(existingUsername: String, requestOptions: RequestOptions): HttpResponse = + update(existingUsername, UserUpdateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /user/{username}`, but is otherwise the same as + * [UserService.delete]. + */ + @MustBeClosed + fun delete( + username: String, + params: UserDeleteParams = UserDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().username(username).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + fun delete(username: String, requestOptions: RequestOptions): HttpResponse = + delete(username, UserDeleteParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `post /user/createWithList`, but is otherwise the same as + * [UserService.createWithList]. + */ + @MustBeClosed + fun createWithList( + params: UserCreateWithListParams = UserCreateWithListParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see createWithList */ + @MustBeClosed + fun createWithList(requestOptions: RequestOptions): HttpResponseFor = + createWithList(UserCreateWithListParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/login`, but is otherwise the same as + * [UserService.login]. + */ + @MustBeClosed + fun login( + params: UserLoginParams = UserLoginParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see login */ + @MustBeClosed + fun login(requestOptions: RequestOptions): HttpResponseFor = + login(UserLoginParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /user/logout`, but is otherwise the same as + * [UserService.logout]. + */ + @MustBeClosed + fun logout( + params: UserLogoutParams = UserLogoutParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see logout */ + @MustBeClosed + fun logout(requestOptions: RequestOptions): HttpResponse = + logout(UserLogoutParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceImpl.kt new file mode 100644 index 0000000..fb2501a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceImpl.kt @@ -0,0 +1,258 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.handlers.stringHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateParams +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserDeleteParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserLogoutParams +import com.pioneer_intergration_app.api.models.users.UserRetrieveParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams + +class UserServiceImpl internal constructor(private val clientOptions: ClientOptions) : UserService { + + private val withRawResponse: UserService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): UserService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): UserService = + UserServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun create(params: UserCreateParams, requestOptions: RequestOptions): User = + // post /user + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve(params: UserRetrieveParams, requestOptions: RequestOptions): User = + // get /user/{username} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun update(params: UserUpdateParams, requestOptions: RequestOptions) { + // put /user/{username} + withRawResponse().update(params, requestOptions) + } + + override fun delete(params: UserDeleteParams, requestOptions: RequestOptions) { + // delete /user/{username} + withRawResponse().delete(params, requestOptions) + } + + override fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): User = + // post /user/createWithList + withRawResponse().createWithList(params, requestOptions).parse() + + override fun login(params: UserLoginParams, requestOptions: RequestOptions): String = + // get /user/login + withRawResponse().login(params, requestOptions).parse() + + override fun logout(params: UserLogoutParams, requestOptions: RequestOptions) { + // get /user/logout + withRawResponse().logout(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + UserService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): UserService.WithRawResponse = + UserServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: UserCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: UserRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val updateHandler: Handler = emptyHandler() + + override fun update( + params: UserUpdateParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("existingUsername", params.existingUsername()) + val request = + HttpRequest.builder() + .method(HttpMethod.PUT) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { updateHandler.handle(it) } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: UserDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("username", params.username()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + + private val createWithListHandler: Handler = + jsonHandler(clientOptions.jsonMapper) + + override fun createWithList( + params: UserCreateWithListParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "createWithList") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createWithListHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val loginHandler: Handler = stringHandler() + + override fun login( + params: UserLoginParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "login") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { loginHandler.handle(it) } + } + } + + private val logoutHandler: Handler = emptyHandler() + + override fun logout( + params: UserLogoutParams, + requestOptions: RequestOptions, + ): HttpResponse { + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("user", "logout") + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { logoutHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderService.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderService.kt new file mode 100644 index 0000000..452a29e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderService.kt @@ -0,0 +1,160 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking.store + +import com.google.errorprone.annotations.MustBeClosed +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +interface OrderService { + + /** + * Returns a view of this service that provides access to raw HTTP responses for each method. + */ + fun withRawResponse(): WithRawResponse + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderService + + /** Place a new order in the store */ + fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see create */ + fun create(order: Order, requestOptions: RequestOptions = RequestOptions.none()): Order = + create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + fun create(requestOptions: RequestOptions): Order = + create(OrderCreateParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate + * exceptions. + */ + fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): Order = retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): Order + + /** @see retrieve */ + fun retrieve(orderId: Long, requestOptions: RequestOptions): Order = + retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will + * generate API errors + */ + fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ) = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + fun delete(params: OrderDeleteParams, requestOptions: RequestOptions = RequestOptions.none()) + + /** @see delete */ + fun delete(orderId: Long, requestOptions: RequestOptions) = + delete(orderId, OrderDeleteParams.none(), requestOptions) + + /** A view of [OrderService] that provides access to raw HTTP responses for each method. */ + interface WithRawResponse { + + /** + * Returns a view of this service with the given option modifications applied. + * + * The original service is not modified. + */ + fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderService.WithRawResponse + + /** + * Returns a raw HTTP response for `post /store/order`, but is otherwise the same as + * [OrderService.create]. + */ + @MustBeClosed + fun create( + params: OrderCreateParams = OrderCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see create */ + @MustBeClosed + fun create( + order: Order, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + create(OrderCreateParams.builder().order(order).build(), requestOptions) + + /** @see create */ + @MustBeClosed + fun create(requestOptions: RequestOptions): HttpResponseFor = + create(OrderCreateParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `get /store/order/{orderId}`, but is otherwise the same + * as [OrderService.retrieve]. + */ + @MustBeClosed + fun retrieve( + orderId: Long, + params: OrderRetrieveParams = OrderRetrieveParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor = + retrieve(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see retrieve */ + @MustBeClosed + fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponseFor + + /** @see retrieve */ + @MustBeClosed + fun retrieve(orderId: Long, requestOptions: RequestOptions): HttpResponseFor = + retrieve(orderId, OrderRetrieveParams.none(), requestOptions) + + /** + * Returns a raw HTTP response for `delete /store/order/{orderId}`, but is otherwise the + * same as [OrderService.delete]. + */ + @MustBeClosed + fun delete( + orderId: Long, + params: OrderDeleteParams = OrderDeleteParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse = delete(params.toBuilder().orderId(orderId).build(), requestOptions) + + /** @see delete */ + @MustBeClosed + fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions = RequestOptions.none(), + ): HttpResponse + + /** @see delete */ + @MustBeClosed + fun delete(orderId: Long, requestOptions: RequestOptions): HttpResponse = + delete(orderId, OrderDeleteParams.none(), requestOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceImpl.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceImpl.kt new file mode 100644 index 0000000..4626113 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceImpl.kt @@ -0,0 +1,141 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking.store + +import com.pioneer_intergration_app.api.core.ClientOptions +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.checkRequired +import com.pioneer_intergration_app.api.core.handlers.emptyHandler +import com.pioneer_intergration_app.api.core.handlers.errorBodyHandler +import com.pioneer_intergration_app.api.core.handlers.errorHandler +import com.pioneer_intergration_app.api.core.handlers.jsonHandler +import com.pioneer_intergration_app.api.core.http.HttpMethod +import com.pioneer_intergration_app.api.core.http.HttpRequest +import com.pioneer_intergration_app.api.core.http.HttpResponse +import com.pioneer_intergration_app.api.core.http.HttpResponse.Handler +import com.pioneer_intergration_app.api.core.http.HttpResponseFor +import com.pioneer_intergration_app.api.core.http.json +import com.pioneer_intergration_app.api.core.http.parseable +import com.pioneer_intergration_app.api.core.prepare +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams +import com.pioneer_intergration_app.api.models.store.orders.OrderDeleteParams +import com.pioneer_intergration_app.api.models.store.orders.OrderRetrieveParams + +class OrderServiceImpl internal constructor(private val clientOptions: ClientOptions) : + OrderService { + + private val withRawResponse: OrderService.WithRawResponse by lazy { + WithRawResponseImpl(clientOptions) + } + + override fun withRawResponse(): OrderService.WithRawResponse = withRawResponse + + override fun withOptions(modifier: (ClientOptions.Builder) -> Unit): OrderService = + OrderServiceImpl(clientOptions.toBuilder().apply(modifier).build()) + + override fun create(params: OrderCreateParams, requestOptions: RequestOptions): Order = + // post /store/order + withRawResponse().create(params, requestOptions).parse() + + override fun retrieve(params: OrderRetrieveParams, requestOptions: RequestOptions): Order = + // get /store/order/{orderId} + withRawResponse().retrieve(params, requestOptions).parse() + + override fun delete(params: OrderDeleteParams, requestOptions: RequestOptions) { + // delete /store/order/{orderId} + withRawResponse().delete(params, requestOptions) + } + + class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : + OrderService.WithRawResponse { + + private val errorHandler: Handler = + errorHandler(errorBodyHandler(clientOptions.jsonMapper)) + + override fun withOptions( + modifier: (ClientOptions.Builder) -> Unit + ): OrderService.WithRawResponse = + OrderServiceImpl.WithRawResponseImpl(clientOptions.toBuilder().apply(modifier).build()) + + private val createHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun create( + params: OrderCreateParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + val request = + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order") + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { createHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val retrieveHandler: Handler = jsonHandler(clientOptions.jsonMapper) + + override fun retrieve( + params: OrderRetrieveParams, + requestOptions: RequestOptions, + ): HttpResponseFor { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response + .use { retrieveHandler.handle(it) } + .also { + if (requestOptions.responseValidation!!) { + it.validate() + } + } + } + } + + private val deleteHandler: Handler = emptyHandler() + + override fun delete( + params: OrderDeleteParams, + requestOptions: RequestOptions, + ): HttpResponse { + // We check here instead of in the params builder because this can be specified + // positionally or in the params class. + checkRequired("orderId", params.orderId()) + val request = + HttpRequest.builder() + .method(HttpMethod.DELETE) + .baseUrl(clientOptions.baseUrl()) + .addPathSegments("store", "order", params._pathParam(0)) + .apply { params._body()?.let { body(json(clientOptions.jsonMapper, it)) } } + .build() + .prepare(clientOptions, params) + val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) + val response = clientOptions.httpClient.execute(request, requestOptions) + return errorHandler.handle(response).parseable { + response.use { deleteHandler.handle(it) } + } + } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro b/pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro new file mode 100644 index 0000000..a944ff3 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro @@ -0,0 +1,32 @@ +# Jackson uses reflection and depends heavily on runtime attributes. +-keepattributes Exceptions,InnerClasses,Signature,Deprecated,*Annotation* + +# Jackson uses Kotlin reflection utilities, which themselves use reflection to access things. +-keep class kotlin.reflect.** { *; } +-keep class kotlin.Metadata { *; } + +# Jackson uses reflection to access enum members (e.g. via `java.lang.Class.getEnumConstants()`). +-keepclassmembers class com.fasterxml.jackson.** extends java.lang.Enum { + ; + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +# Jackson uses reflection to access annotation members. +-keepclassmembers @interface com.fasterxml.jackson.annotation.** { + *; +} + +# Jackson uses reified type information to serialize and deserialize our classes (via `TypeReference`). +-keep class com.fasterxml.jackson.core.type.TypeReference { *; } +-keep class * extends com.fasterxml.jackson.core.type.TypeReference { *; } + +# Jackson uses reflection to access our class serializers and deserializers. +-keep @com.fasterxml.jackson.databind.annotation.JsonSerialize class com.pioneer_intergration_app.api.** { *; } +-keep @com.fasterxml.jackson.databind.annotation.JsonDeserialize class com.pioneer_intergration_app.api.** { *; } + +# Jackson uses reflection to serialize and deserialize our classes based on their constructors and annotated members. +-keepclassmembers class com.pioneer_intergration_app.api.** { + (...); + @com.fasterxml.jackson.annotation.* *; +} \ No newline at end of file diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/TestServerExtension.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/TestServerExtension.kt new file mode 100644 index 0000000..3f4deac --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/TestServerExtension.kt @@ -0,0 +1,62 @@ +package com.pioneer_intergration_app.api + +import java.lang.RuntimeException +import java.net.URL +import org.junit.jupiter.api.extension.BeforeAllCallback +import org.junit.jupiter.api.extension.ConditionEvaluationResult +import org.junit.jupiter.api.extension.ExecutionCondition +import org.junit.jupiter.api.extension.ExtensionContext + +class TestServerExtension : BeforeAllCallback, ExecutionCondition { + + override fun beforeAll(context: ExtensionContext?) { + try { + URL(BASE_URL).openConnection().connect() + } catch (e: Exception) { + throw RuntimeException( + """ + The test suite will not run without a mock Prism 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 + """ + .trimIndent(), + e, + ) + } + } + + override fun evaluateExecutionCondition(context: ExtensionContext): ConditionEvaluationResult { + return if (System.getenv(SKIP_TESTS_ENV).toBoolean()) { + ConditionEvaluationResult.disabled( + "Environment variable $SKIP_TESTS_ENV is set to true" + ) + } else { + ConditionEvaluationResult.enabled( + "Environment variable $SKIP_TESTS_ENV is not set to true" + ) + } + } + + companion object { + + val BASE_URL = System.getenv("TEST_API_BASE_URL") ?: "http://localhost:4010" + + const val SKIP_TESTS_ENV: String = "SKIP_MOCK_TESTS" + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ClientOptionsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ClientOptionsTest.kt new file mode 100644 index 0000000..1c5dd0f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ClientOptionsTest.kt @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.core + +import com.pioneer_intergration_app.api.core.http.HttpClient +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify + +@ExtendWith(MockitoExtension::class) +internal class ClientOptionsTest { + + private val httpClient = mock() + + @Test + fun toBuilder_whenOriginalClientOptionsGarbageCollected_doesNotCloseOriginalClient() { + var clientOptions = + ClientOptions.builder().httpClient(httpClient).apiKey("My API Key").build() + verify(httpClient, never()).close() + + // Overwrite the `clientOptions` variable so that the original `ClientOptions` is GC'd. + clientOptions = clientOptions.toBuilder().build() + System.gc() + Thread.sleep(100) + + verify(httpClient, never()).close() + // This exists so that `clientOptions` is still reachable. + assertThat(clientOptions).isEqualTo(clientOptions) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt new file mode 100644 index 0000000..7ceb54d --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt @@ -0,0 +1,102 @@ +package com.pioneer_intergration_app.api.core + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.exc.MismatchedInputException +import com.fasterxml.jackson.module.kotlin.readValue +import java.time.LocalDateTime +import kotlin.reflect.KClass +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.catchThrowable +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertDoesNotThrow +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource +import org.junitpioneer.jupiter.cartesian.CartesianTest + +internal class ObjectMappersTest { + + internal class ClassWithBooleanFieldPrefixedWithIs(private val isActive: JsonField) { + + @JsonProperty("is_active") @ExcludeMissing fun _isActive() = isActive + } + + @Test + fun write_whenFieldPrefixedWithIs_keepsPrefix() { + val value = ClassWithBooleanFieldPrefixedWithIs(JsonField.of(true)) + + val json = jsonMapper().writeValueAsString(value) + + assertThat(json).isEqualTo("{\"is_active\":true}") + } + + internal class Class(@get:JsonProperty("field") @JsonProperty("field") val field: String) + + enum class ShapeTestCase(val value: Any, val kClass: KClass<*>) { + STRING("Hello World!", String::class), + BOOLEAN(true, Boolean::class), + FLOAT(3.14F, Float::class), + DOUBLE(3.14, Double::class), + INTEGER(42, Int::class), + LONG(42L, Long::class), + MAP(mapOf("property" to "value"), Map::class), + CLASS(Class("Hello World!"), Class::class), + LIST(listOf(1, 2, 3), List::class); + + companion object { + val VALID_CONVERSIONS = + listOf( + FLOAT to DOUBLE, + FLOAT to INTEGER, + FLOAT to LONG, + DOUBLE to FLOAT, + DOUBLE to INTEGER, + DOUBLE to LONG, + INTEGER to FLOAT, + INTEGER to DOUBLE, + INTEGER to LONG, + LONG to FLOAT, + LONG to DOUBLE, + LONG to INTEGER, + CLASS to MAP, + // These aren't actually valid, but coercion configs don't work for String until + // v2.14.0: https://github.com/FasterXML/jackson-databind/issues/3240 + // We currently test on v2.13.4. + BOOLEAN to STRING, + FLOAT to STRING, + DOUBLE to STRING, + INTEGER to STRING, + LONG to STRING, + ) + } + } + + @CartesianTest + fun read(@CartesianTest.Enum shape1: ShapeTestCase, @CartesianTest.Enum shape2: ShapeTestCase) { + val jsonMapper = jsonMapper() + val json = jsonMapper.writeValueAsString(shape1.value) + + val e = catchThrowable { jsonMapper.readValue(json, shape2.kClass.java) } + + if (shape1 == shape2 || shape1 to shape2 in ShapeTestCase.VALID_CONVERSIONS) { + assertThat(e).isNull() + } else { + assertThat(e).isInstanceOf(MismatchedInputException::class.java) + } + } + + enum class LenientLocalDateTimeTestCase(val string: String) { + DATE("1998-04-21"), + DATE_TIME("1998-04-21T04:00:00"), + ZONED_DATE_TIME_1("1998-04-21T04:00:00+03:00"), + ZONED_DATE_TIME_2("1998-04-21T04:00:00Z"), + } + + @ParameterizedTest + @EnumSource + fun readLocalDateTime_lenient(testCase: LenientLocalDateTimeTestCase) { + val jsonMapper = jsonMapper() + val json = jsonMapper.writeValueAsString(testCase.string) + + assertDoesNotThrow { jsonMapper().readValue(json) } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableTest.kt new file mode 100644 index 0000000..1e9f4b4 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/PhantomReachableTest.kt @@ -0,0 +1,27 @@ +package com.pioneer_intergration_app.api.core + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PhantomReachableTest { + + @Test + fun closeWhenPhantomReachable_whenObservedIsGarbageCollected_closesCloseable() { + var closed = false + val closeable = AutoCloseable { closed = true } + + closeWhenPhantomReachable( + // Pass an inline object for the object to observe so that it becomes immediately + // unreachable. + Any(), + closeable, + ) + + assertThat(closed).isFalse() + + System.gc() + Thread.sleep(100) + + assertThat(closed).isTrue() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/UtilsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/UtilsTest.kt new file mode 100644 index 0000000..84b042f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/UtilsTest.kt @@ -0,0 +1,33 @@ +package com.pioneer_intergration_app.api.core + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UtilsTest { + @Test + fun contentDeepEquals() { + assertThat(42 contentEquals 42).isTrue() + assertThat(42 contentEquals "Hello World!").isFalse() + assertThat(byteArrayOf(1, 2, 3) contentEquals byteArrayOf(1, 2, 3)).isTrue() + assertThat(byteArrayOf(1, 2, 3) contentEquals byteArrayOf(1, 2, 4)).isFalse() + assertThat( + arrayOf(byteArrayOf(1, 2), byteArrayOf(3)) contentEquals + arrayOf(byteArrayOf(1, 2), byteArrayOf(3)) + ) + .isTrue() + assertThat( + arrayOf(byteArrayOf(1, 2), byteArrayOf(3)) contentEquals + arrayOf(byteArrayOf(1), byteArrayOf(2, 3)) + ) + .isFalse() + } + + @Test + fun contentToString() { + assertThat((42).contentToString()).isEqualTo("42") + assertThat("Hello World!".contentToString()).isEqualTo("Hello World!") + assertThat(byteArrayOf(1, 2, 3).contentToString()).isEqualTo("[1, 2, 3]") + assertThat(arrayOf(byteArrayOf(1, 2), byteArrayOf(3)).contentToString()) + .isEqualTo("[[1, 2], [3]]") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ValuesTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ValuesTest.kt new file mode 100644 index 0000000..4fbcaec --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ValuesTest.kt @@ -0,0 +1,127 @@ +package com.pioneer_intergration_app.api.core + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class ValuesTest { + companion object { + private val NON_JSON = Any() + } + + enum class TestCase( + val value: JsonField<*>, + val expectedIsMissing: Boolean = false, + val expectedIsNull: Boolean = false, + val expectedAsKnown: Any? = null, + val expectedAsBoolean: Boolean? = null, + val expectedAsNumber: Number? = null, + val expectedAsString: String? = null, + val expectedAsArray: List? = null, + val expectedAsObject: Map? = null, + ) { + MISSING(JsonMissing.of(), expectedIsMissing = true), + NULL(JsonNull.of(), expectedIsNull = true), + KNOWN(KnownValue.of(NON_JSON), expectedAsKnown = NON_JSON), + KNOWN_BOOLEAN(KnownValue.of(true), expectedAsKnown = true, expectedAsBoolean = true), + BOOLEAN(JsonBoolean.of(true), expectedAsBoolean = true), + KNOWN_NUMBER(KnownValue.of(42), expectedAsKnown = 42, expectedAsNumber = 42), + NUMBER(JsonNumber.of(42), expectedAsNumber = 42), + KNOWN_STRING(KnownValue.of("hello"), expectedAsKnown = "hello", expectedAsString = "hello"), + STRING(JsonString.of("hello"), expectedAsString = "hello"), + KNOWN_ARRAY_NOT_ALL_JSON( + KnownValue.of(listOf("a", "b", NON_JSON)), + expectedAsKnown = listOf("a", "b", NON_JSON), + ), + KNOWN_ARRAY( + KnownValue.of(listOf("a", "b", "c")), + expectedAsKnown = listOf("a", "b", "c"), + expectedAsArray = listOf(JsonString.of("a"), JsonString.of("b"), JsonString.of("c")), + ), + ARRAY( + JsonArray.of(listOf(JsonString.of("a"), JsonString.of("b"), JsonString.of("c"))), + expectedAsArray = listOf(JsonString.of("a"), JsonString.of("b"), JsonString.of("c")), + ), + KNOWN_OBJECT_NOT_ALL_STRING_KEYS( + KnownValue.of(mapOf("a" to "b", 42 to "c")), + expectedAsKnown = mapOf("a" to "b", 42 to "c"), + ), + KNOWN_OBJECT_NOT_ALL_JSON( + KnownValue.of(mapOf("a" to "b", "b" to NON_JSON)), + expectedAsKnown = mapOf("a" to "b", "b" to NON_JSON), + ), + KNOWN_OBJECT( + KnownValue.of(mapOf("a" to "b", "b" to "c")), + expectedAsKnown = mapOf("a" to "b", "b" to "c"), + expectedAsObject = mapOf("a" to JsonString.of("b"), "b" to JsonString.of("c")), + ), + OBJECT( + JsonObject.of(mapOf("a" to JsonString.of("b"), "b" to JsonString.of("c"))), + expectedAsObject = mapOf("a" to JsonString.of("b"), "b" to JsonString.of("c")), + ), + } + + @ParameterizedTest + @EnumSource + fun isMissing(testCase: TestCase) { + val isMissing = testCase.value.isMissing() + + assertThat(isMissing).isEqualTo(testCase.expectedIsMissing) + } + + @ParameterizedTest + @EnumSource + fun isNull(testCase: TestCase) { + val isNull = testCase.value.isNull() + + assertThat(isNull).isEqualTo(testCase.expectedIsNull) + } + + @ParameterizedTest + @EnumSource + fun asKnown(testCase: TestCase) { + val known = testCase.value.asKnown() + + assertThat(known).isEqualTo(testCase.expectedAsKnown) + } + + @ParameterizedTest + @EnumSource + fun asBoolean(testCase: TestCase) { + val boolean = testCase.value.asBoolean() + + assertThat(boolean).isEqualTo(testCase.expectedAsBoolean) + } + + @ParameterizedTest + @EnumSource + fun asNumber(testCase: TestCase) { + val number = testCase.value.asNumber() + + assertThat(number).isEqualTo(testCase.expectedAsNumber) + } + + @ParameterizedTest + @EnumSource + fun asString(testCase: TestCase) { + val string = testCase.value.asString() + + assertThat(string).isEqualTo(testCase.expectedAsString) + } + + @ParameterizedTest + @EnumSource + fun asArray(testCase: TestCase) { + val array = testCase.value.asArray() + + assertThat(array).isEqualTo(testCase.expectedAsArray) + } + + @ParameterizedTest + @EnumSource + fun asObject(testCase: TestCase) { + val obj = testCase.value.asObject() + + assertThat(obj).isEqualTo(testCase.expectedAsObject) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HeadersTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HeadersTest.kt new file mode 100644 index 0000000..7385d36 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HeadersTest.kt @@ -0,0 +1,242 @@ +package com.pioneer_intergration_app.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class HeadersTest { + + enum class TestCase( + val headers: Headers, + val expectedMap: Map>, + val expectedSize: Int, + ) { + EMPTY(Headers.builder().build(), expectedMap = mapOf(), expectedSize = 0), + PUT_ONE( + Headers.builder().put("name", "value").build(), + expectedMap = mapOf("name" to listOf("value")), + expectedSize = 1, + ), + PUT_MULTIPLE( + Headers.builder().put("name", listOf("value1", "value2")).build(), + expectedMap = mapOf("name" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT( + Headers.builder().put("name1", "value").put("name2", "value").build(), + expectedMap = mapOf("name1" to listOf("value"), "name2" to listOf("value")), + expectedSize = 2, + ), + MULTIPLE_PUT_SAME_NAME( + Headers.builder().put("name", "value1").put("name", "value2").build(), + expectedMap = mapOf("name" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT_MULTIPLE( + Headers.builder() + .put("name", listOf("value1", "value2")) + .put("name", listOf("value1", "value2")) + .build(), + expectedMap = mapOf("name" to listOf("value1", "value2", "value1", "value2")), + expectedSize = 4, + ), + PUT_CASE_INSENSITIVE( + Headers.builder() + .put("name", "value1") + .put("NAME", "value2") + .put("nAmE", "value3") + .build(), + expectedMap = mapOf("name" to listOf("value1", "value2", "value3")), + expectedSize = 3, + ), + PUT_ALL_MAP( + Headers.builder() + .putAll( + mapOf( + "name1" to listOf("value1", "value2"), + "name2" to listOf("value1", "value2"), + ) + ) + .build(), + expectedMap = + mapOf("name1" to listOf("value1", "value2"), "name2" to listOf("value1", "value2")), + expectedSize = 4, + ), + PUT_ALL_HEADERS( + Headers.builder().putAll(Headers.builder().put("name", "value").build()).build(), + expectedMap = mapOf("name" to listOf("value")), + expectedSize = 1, + ), + PUT_ALL_CASE_INSENSITIVE( + Headers.builder() + .putAll( + mapOf( + "name" to listOf("value1"), + "NAME" to listOf("value2"), + "nAmE" to listOf("value3"), + ) + ) + .build(), + expectedMap = mapOf("name" to listOf("value1", "value2", "value3")), + expectedSize = 3, + ), + REMOVE_ABSENT( + Headers.builder().remove("name").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_ONE( + Headers.builder().put("name", "value").remove("name").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_MULTIPLE( + Headers.builder().put("name", listOf("value1", "value2")).remove("name").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_CASE_INSENSITIVE( + Headers.builder().put("name", listOf("value1", "value2")).remove("NAME").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_ALL( + Headers.builder() + .put("name1", "value") + .put("name3", "value") + .removeAll(setOf("name1", "name2", "name3")) + .build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_ALL_CASE_INSENSITIVE( + Headers.builder() + .put("name1", "value") + .put("name3", "value") + .removeAll(setOf("NAME1", "nAmE3")) + .build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + CLEAR( + Headers.builder().put("name1", "value").put("name2", "value").clear().build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REPLACE_ONE_ABSENT( + Headers.builder().replace("name", "value").build(), + expectedMap = mapOf("name" to listOf("value")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_ONE( + Headers.builder().put("name", "value1").replace("name", "value2").build(), + expectedMap = mapOf("name" to listOf("value2")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_MULTIPLE( + Headers.builder() + .put("name", listOf("value1", "value2")) + .replace("name", "value3") + .build(), + expectedMap = mapOf("name" to listOf("value3")), + expectedSize = 1, + ), + REPLACE_MULTIPLE_ABSENT( + Headers.builder().replace("name", listOf("value1", "value2")).build(), + expectedMap = mapOf("name" to listOf("value1", "value2")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_ONE( + Headers.builder() + .put("name", "value1") + .replace("name", listOf("value2", "value3")) + .build(), + expectedMap = mapOf("name" to listOf("value2", "value3")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_MULTIPLE( + Headers.builder() + .put("name", listOf("value1", "value2")) + .replace("name", listOf("value3", "value4")) + .build(), + expectedMap = mapOf("name" to listOf("value3", "value4")), + expectedSize = 2, + ), + REPLACE_CASE_INSENSITIVE( + Headers.builder() + .put("name", "value1") + .replace("NAME", listOf("value2", "value3")) + .build(), + expectedMap = mapOf("NAME" to listOf("value2", "value3")), + expectedSize = 2, + ), + REPLACE_ALL_MAP( + Headers.builder() + .put("name1", "value1") + .put("name2", "value1") + .put("name3", "value1") + .replaceAll(mapOf("name1" to listOf("value2"), "name3" to listOf("value2"))) + .build(), + expectedMap = + mapOf( + "name1" to listOf("value2"), + "name2" to listOf("value1"), + "name3" to listOf("value2"), + ), + expectedSize = 3, + ), + REPLACE_ALL_HEADERS( + Headers.builder() + .put("name1", "value1") + .put("name2", "value1") + .put("name3", "value1") + .replaceAll(Headers.builder().put("name1", "value2").put("name3", "value2").build()) + .build(), + expectedMap = + mapOf( + "name1" to listOf("value2"), + "name2" to listOf("value1"), + "name3" to listOf("value2"), + ), + expectedSize = 3, + ), + REPLACE_ALL_CASE_INSENSITIVE( + Headers.builder() + .put("name1", "value1") + .put("name2", "value1") + .replaceAll(mapOf("NAME1" to listOf("value2"), "nAmE2" to listOf("value2"))) + .build(), + expectedMap = mapOf("NAME1" to listOf("value2"), "nAmE2" to listOf("value2")), + expectedSize = 2, + ), + } + + @ParameterizedTest + @EnumSource + fun namesAndValues(testCase: TestCase) { + val map = mutableMapOf>() + val headers = testCase.headers + headers.names().forEach { name -> map[name] = headers.values(name) } + + assertThat(map).isEqualTo(testCase.expectedMap) + } + + @ParameterizedTest + @EnumSource + fun caseInsensitiveNames(testCase: TestCase) { + val headers = testCase.headers + + for (name in headers.names()) { + assertThat(headers.values(name)).isEqualTo(headers.values(name.lowercase())) + assertThat(headers.values(name)).isEqualTo(headers.values(name.uppercase())) + } + } + + @ParameterizedTest + @EnumSource + fun size(testCase: TestCase) { + val size = testCase.headers.size + + assertThat(size).isEqualTo(testCase.expectedSize) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestTest.kt new file mode 100644 index 0000000..6ca9b7f --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/HttpRequestTest.kt @@ -0,0 +1,110 @@ +package com.pioneer_intergration_app.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class HttpRequestTest { + + enum class UrlTestCase(val request: HttpRequest, val expectedUrl: String) { + BASE_URL_ONLY( + HttpRequest.builder().method(HttpMethod.GET).baseUrl("https://api.example.com").build(), + expectedUrl = "https://api.example.com", + ), + BASE_URL_WITH_TRAILING_SLASH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .build(), + expectedUrl = "https://api.example.com/", + ), + SINGLE_PATH_SEGMENT( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + MULTIPLE_PATH_SEGMENTS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegments("users", "123", "profile") + .build(), + expectedUrl = "https://api.example.com/users/123/profile", + ), + PATH_SEGMENT_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("user name") + .build(), + expectedUrl = "https://api.example.com/user+name", + ), + SINGLE_QUERY_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .build(), + expectedUrl = "https://api.example.com/users?limit=10", + ), + MULTIPLE_QUERY_PARAMS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParam("limit", "10") + .putQueryParam("offset", "20") + .build(), + expectedUrl = "https://api.example.com/users?limit=10&offset=20", + ), + QUERY_PARAM_WITH_SPECIAL_CHARS( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("search") + .putQueryParam("q", "hello world") + .build(), + expectedUrl = "https://api.example.com/search?q=hello+world", + ), + MULTIPLE_VALUES_SAME_PARAM( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com") + .addPathSegment("users") + .putQueryParams("tags", listOf("admin", "user")) + .build(), + expectedUrl = "https://api.example.com/users?tags=admin&tags=user", + ), + BASE_URL_WITH_TRAILING_SLASH_AND_PATH( + HttpRequest.builder() + .method(HttpMethod.GET) + .baseUrl("https://api.example.com/") + .addPathSegment("users") + .build(), + expectedUrl = "https://api.example.com/users", + ), + COMPLEX_URL( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl("https://api.example.com") + .addPathSegments("v1", "users", "123") + .putQueryParams("include", listOf("profile", "settings")) + .putQueryParam("format", "json") + .build(), + expectedUrl = + "https://api.example.com/v1/users/123?include=profile&include=settings&format=json", + ), + } + + @ParameterizedTest + @EnumSource + fun url(testCase: UrlTestCase) { + val actualUrl = testCase.request.url() + + assertThat(actualUrl).isEqualTo(testCase.expectedUrl) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/QueryParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/QueryParamsTest.kt new file mode 100644 index 0000000..6d0d584 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/QueryParamsTest.kt @@ -0,0 +1,180 @@ +package com.pioneer_intergration_app.api.core.http + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +internal class QueryParamsTest { + + enum class TestCase( + val queryParams: QueryParams, + val expectedMap: Map>, + val expectedSize: Int, + ) { + EMPTY(QueryParams.builder().build(), expectedMap = mapOf(), expectedSize = 0), + PUT_ONE( + QueryParams.builder().put("key", "value").build(), + expectedMap = mapOf("key" to listOf("value")), + expectedSize = 1, + ), + PUT_MULTIPLE( + QueryParams.builder().put("key", listOf("value1", "value2")).build(), + expectedMap = mapOf("key" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT( + QueryParams.builder().put("key1", "value").put("key2", "value").build(), + expectedMap = mapOf("key1" to listOf("value"), "key2" to listOf("value")), + expectedSize = 2, + ), + MULTIPLE_PUT_SAME_NAME( + QueryParams.builder().put("key", "value1").put("key", "value2").build(), + expectedMap = mapOf("key" to listOf("value1", "value2")), + expectedSize = 2, + ), + MULTIPLE_PUT_MULTIPLE( + QueryParams.builder() + .put("key", listOf("value1", "value2")) + .put("key", listOf("value1", "value2")) + .build(), + expectedMap = mapOf("key" to listOf("value1", "value2", "value1", "value2")), + expectedSize = 4, + ), + PUT_ALL_MAP( + QueryParams.builder() + .putAll( + mapOf( + "key1" to listOf("value1", "value2"), + "key2" to listOf("value1", "value2"), + ) + ) + .build(), + expectedMap = + mapOf("key1" to listOf("value1", "value2"), "key2" to listOf("value1", "value2")), + expectedSize = 4, + ), + PUT_ALL_HEADERS( + QueryParams.builder().putAll(QueryParams.builder().put("key", "value").build()).build(), + expectedMap = mapOf("key" to listOf("value")), + expectedSize = 1, + ), + REMOVE_ABSENT( + QueryParams.builder().remove("key").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_ONE( + QueryParams.builder().put("key", "value").remove("key").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_PRESENT_MULTIPLE( + QueryParams.builder().put("key", listOf("value1", "value2")).remove("key").build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REMOVE_ALL( + QueryParams.builder() + .put("key1", "value") + .put("key3", "value") + .removeAll(setOf("key1", "key2", "key3")) + .build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + CLEAR( + QueryParams.builder().put("key1", "value").put("key2", "value").clear().build(), + expectedMap = mapOf(), + expectedSize = 0, + ), + REPLACE_ONE_ABSENT( + QueryParams.builder().replace("key", "value").build(), + expectedMap = mapOf("key" to listOf("value")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_ONE( + QueryParams.builder().put("key", "value1").replace("key", "value2").build(), + expectedMap = mapOf("key" to listOf("value2")), + expectedSize = 1, + ), + REPLACE_ONE_PRESENT_MULTIPLE( + QueryParams.builder() + .put("key", listOf("value1", "value2")) + .replace("key", "value3") + .build(), + expectedMap = mapOf("key" to listOf("value3")), + expectedSize = 1, + ), + REPLACE_MULTIPLE_ABSENT( + QueryParams.builder().replace("key", listOf("value1", "value2")).build(), + expectedMap = mapOf("key" to listOf("value1", "value2")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_ONE( + QueryParams.builder() + .put("key", "value1") + .replace("key", listOf("value2", "value3")) + .build(), + expectedMap = mapOf("key" to listOf("value2", "value3")), + expectedSize = 2, + ), + REPLACE_MULTIPLE_PRESENT_MULTIPLE( + QueryParams.builder() + .put("key", listOf("value1", "value2")) + .replace("key", listOf("value3", "value4")) + .build(), + expectedMap = mapOf("key" to listOf("value3", "value4")), + expectedSize = 2, + ), + REPLACE_ALL_MAP( + QueryParams.builder() + .put("key1", "value1") + .put("key2", "value1") + .put("key3", "value1") + .replaceAll(mapOf("key1" to listOf("value2"), "key3" to listOf("value2"))) + .build(), + expectedMap = + mapOf( + "key1" to listOf("value2"), + "key2" to listOf("value1"), + "key3" to listOf("value2"), + ), + expectedSize = 3, + ), + REPLACE_ALL_HEADERS( + QueryParams.builder() + .put("key1", "value1") + .put("key2", "value1") + .put("key3", "value1") + .replaceAll( + QueryParams.builder().put("key1", "value2").put("key3", "value2").build() + ) + .build(), + expectedMap = + mapOf( + "key1" to listOf("value2"), + "key2" to listOf("value1"), + "key3" to listOf("value2"), + ), + expectedSize = 3, + ), + } + + @ParameterizedTest + @EnumSource + fun keysAndValues(testCase: TestCase) { + val map = mutableMapOf>() + val queryParams = testCase.queryParams + queryParams.keys().forEach { key -> map[key] = queryParams.values(key) } + + assertThat(map).isEqualTo(testCase.expectedMap) + } + + @ParameterizedTest + @EnumSource + fun size(testCase: TestCase) { + val size = testCase.queryParams.size + + assertThat(size).isEqualTo(testCase.expectedSize) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClientTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClientTest.kt new file mode 100644 index 0000000..6de2c8b --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClientTest.kt @@ -0,0 +1,353 @@ +package com.pioneer_intergration_app.api.core.http + +import com.github.tomakehurst.wiremock.client.WireMock.* +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import com.github.tomakehurst.wiremock.stubbing.Scenario +import com.pioneer_intergration_app.api.client.okhttp.OkHttpClient +import com.pioneer_intergration_app.api.core.RequestOptions +import com.pioneer_intergration_app.api.core.Sleeper +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppRetryableException +import java.io.InputStream +import java.time.Duration +import kotlinx.coroutines.runBlocking +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.parallel.ResourceLock +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class RetryingHttpClientTest { + + private var openResponseCount = 0 + private lateinit var baseUrl: String + private lateinit var httpClient: HttpClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + baseUrl = wmRuntimeInfo.httpBaseUrl + val okHttpClient = OkHttpClient.builder().build() + httpClient = + object : HttpClient { + + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = trackClose(okHttpClient.execute(request, requestOptions)) + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse = trackClose(okHttpClient.executeAsync(request, requestOptions)) + + override fun close() = okHttpClient.close() + + private fun trackClose(response: HttpResponse): HttpResponse { + openResponseCount++ + return object : HttpResponse { + + private var isClosed = false + + override fun statusCode(): Int = response.statusCode() + + override fun headers(): Headers = response.headers() + + override fun body(): InputStream = response.body() + + override fun close() { + response.close() + if (isClosed) { + return + } + openResponseCount-- + isClosed = true + } + } + } + } + resetAllScenarios() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) + val retryingClient = retryingHttpClientBuilder().build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withIdempotencyHeader(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .withHeader("X-Some-Header", matching("stainless-java-retry-.+")) + .willReturn(ok()) + ) + val retryingClient = + retryingHttpClientBuilder().maxRetries(2).idempotencyHeader("X-Some-Header").build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify(1, postRequestedFor(urlPathEqualTo("/something"))) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterHeader(async: Boolean) { + 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") + ) + .willSetStateTo("RETRY_AFTER_DATE") + ) + stubFor( + post(urlPathEqualTo("/something")) + // Then we fail with a retry after header given as a delay + .inScenario("foo") + .whenScenarioStateIs("RETRY_AFTER_DATE") + .willReturn(serviceUnavailable().withHeader("Retry-After", "1.234")) + .willSetStateTo("RETRY_AFTER_DELAY") + ) + stubFor( + post(urlPathEqualTo("/something")) + // Then we return a success + .inScenario("foo") + .whenScenarioStateIs("RETRY_AFTER_DELAY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("0")), + ) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("1")), + ) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("2")), + ) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withOverwrittenRetryCountHeader(async: Boolean) { + 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") + ) + .willSetStateTo("RETRY_AFTER_DATE") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") // then we return a success + .whenScenarioStateIs("RETRY_AFTER_DATE") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val retryingClient = retryingHttpClientBuilder().maxRetries(2).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .putHeader("x-stainless-retry-count", "42") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify( + 2, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("42")), + ) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryAfterMsHeader(async: Boolean) { + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") + .whenScenarioStateIs(Scenario.STARTED) + .willReturn(serviceUnavailable().withHeader("Retry-After-Ms", "10")) + .willSetStateTo("RETRY_AFTER_DELAY") + ) + stubFor( + post(urlPathEqualTo("/something")) + .inScenario("foo") // then we return a success + .whenScenarioStateIs("RETRY_AFTER_DELAY") + .willReturn(ok()) + .willSetStateTo("COMPLETED") + ) + val retryingClient = retryingHttpClientBuilder().maxRetries(1).build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify(2, postRequestedFor(urlPathEqualTo("/something"))) + assertNoResponseLeaks() + } + + @ParameterizedTest + @ValueSource(booleans = [false, true]) + fun execute_withRetryableException(async: Boolean) { + stubFor(post(urlPathEqualTo("/something")).willReturn(ok())) + + var callCount = 0 + val failingHttpClient = + object : HttpClient { + override fun execute( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + callCount++ + if (callCount == 1) { + throw PioneerIntergrationAppRetryableException( + "Simulated retryable failure" + ) + } + return httpClient.execute(request, requestOptions) + } + + override suspend fun executeAsync( + request: HttpRequest, + requestOptions: RequestOptions, + ): HttpResponse { + callCount++ + if (callCount == 1) { + throw PioneerIntergrationAppRetryableException( + "Simulated retryable failure" + ) + } + return httpClient.executeAsync(request, requestOptions) + } + + override fun close() = httpClient.close() + } + + val retryingClient = + RetryingHttpClient.builder() + .httpClient(failingHttpClient) + .maxRetries(2) + .sleeper( + object : Sleeper { + + override fun sleep(duration: Duration) {} + + override suspend fun sleepAsync(duration: Duration) {} + + override fun close() {} + } + ) + .build() + + val response = + retryingClient.execute( + HttpRequest.builder() + .method(HttpMethod.POST) + .baseUrl(baseUrl) + .addPathSegment("something") + .build(), + async, + ) + + assertThat(response.statusCode()).isEqualTo(200) + verify( + 1, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("1")), + ) + verify( + 0, + postRequestedFor(urlPathEqualTo("/something")) + .withHeader("x-stainless-retry-count", equalTo("0")), + ) + assertNoResponseLeaks() + } + + private fun retryingHttpClientBuilder() = + RetryingHttpClient.builder() + .httpClient(httpClient) + // Use a no-op `Sleeper` to make the test fast. + .sleeper( + object : Sleeper { + + override fun sleep(duration: Duration) {} + + override suspend fun sleepAsync(duration: Duration) {} + + override fun close() {} + } + ) + + private fun HttpClient.execute(request: HttpRequest, async: Boolean): HttpResponse = + if (async) runBlocking { executeAsync(request) } else execute(request) + + // When retrying, all failed responses should be closed. Only the final returned response should + // be open. + private fun assertNoResponseLeaks() = assertThat(openResponseCount).isEqualTo(1) +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/OrderTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/OrderTest.kt new file mode 100644 index 0000000..9444dcd --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/OrderTest.kt @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderTest { + + @Test + fun create() { + val order = + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + + assertThat(order.id()).isEqualTo(10L) + assertThat(order.complete()).isEqualTo(true) + assertThat(order.petId()).isEqualTo(198772L) + assertThat(order.quantity()).isEqualTo(7) + assertThat(order.shipDate()).isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(order.status()).isEqualTo(Order.Status.APPROVED) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val order = + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + + val roundtrippedOrder = + jsonMapper.readValue(jsonMapper.writeValueAsString(order), jacksonTypeRef()) + + assertThat(roundtrippedOrder).isEqualTo(order) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/CategoryTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/CategoryTest.kt new file mode 100644 index 0000000..1e1aaf7 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/CategoryTest.kt @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class CategoryTest { + + @Test + fun create() { + val category = Category.builder().id(1L).name("Dogs").build() + + assertThat(category.id()).isEqualTo(1L) + assertThat(category.name()).isEqualTo("Dogs") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val category = Category.builder().id(1L).name("Dogs").build() + + val roundtrippedCategory = + jsonMapper.readValue( + jsonMapper.writeValueAsString(category), + jacksonTypeRef(), + ) + + assertThat(roundtrippedCategory).isEqualTo(category) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParamsTest.kt new file mode 100644 index 0000000..ffb5ec2 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetCreateParamsTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetCreateParamsTest { + + @Test + fun create() { + PetCreateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + PetCreateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + PetCreateParams.builder() + .pet(Pet.builder().name("doggie").addPhotoUrl("string").build()) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(Pet.builder().name("doggie").addPhotoUrl("string").build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParamsTest.kt new file mode 100644 index 0000000..0db30b9 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetDeleteParamsTest { + + @Test + fun create() { + PetDeleteParams.builder().petId(0L).build() + } + + @Test + fun pathParams() { + val params = PetDeleteParams.builder().petId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParamsTest.kt new file mode 100644 index 0000000..d0433c0 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByStatusParamsTest.kt @@ -0,0 +1,34 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetFindByStatusParamsTest { + + @Test + fun create() { + PetFindByStatusParams.builder().status(PetFindByStatusParams.Status.AVAILABLE).build() + } + + @Test + fun queryParams() { + val params = + PetFindByStatusParams.builder().status(PetFindByStatusParams.Status.AVAILABLE).build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().put("status", "available").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetFindByStatusParams.builder().build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParamsTest.kt new file mode 100644 index 0000000..1d87fe5 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetFindByTagsParamsTest.kt @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetFindByTagsParamsTest { + + @Test + fun create() { + PetFindByTagsParams.builder().addTag("string").build() + } + + @Test + fun queryParams() { + val params = PetFindByTagsParams.builder().addTag("string").build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder().put("tags", listOf("string").joinToString(",")).build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetFindByTagsParams.builder().build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParamsTest.kt new file mode 100644 index 0000000..7e9e558 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetRetrieveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetRetrieveParamsTest { + + @Test + fun create() { + PetRetrieveParams.builder().petId(0L).build() + } + + @Test + fun pathParams() { + val params = PetRetrieveParams.builder().petId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetTest.kt new file mode 100644 index 0000000..e2da096 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetTest.kt @@ -0,0 +1,50 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetTest { + + @Test + fun create() { + val pet = + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + + assertThat(pet.name()).isEqualTo("doggie") + assertThat(pet.photoUrls()).containsExactly("string") + assertThat(pet.id()).isEqualTo(10L) + assertThat(pet.category()).isEqualTo(Category.builder().id(1L).name("Dogs").build()) + assertThat(pet.status()).isEqualTo(Pet.Status.AVAILABLE) + assertThat(pet.tags()).containsExactly(Pet.Tag.builder().id(0L).name("name").build()) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val pet = + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + + val roundtrippedPet = + jsonMapper.readValue(jsonMapper.writeValueAsString(pet), jacksonTypeRef()) + + assertThat(roundtrippedPet).isEqualTo(pet) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParamsTest.kt new file mode 100644 index 0000000..e9df453 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateByIdParamsTest.kt @@ -0,0 +1,43 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUpdateByIdParamsTest { + + @Test + fun create() { + PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + } + + @Test + fun pathParams() { + val params = PetUpdateByIdParams.builder().petId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo(QueryParams.builder().put("name", "name").put("status", "status").build()) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetUpdateByIdParams.builder().petId(0L).build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParamsTest.kt new file mode 100644 index 0000000..57d2449 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUpdateParamsTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUpdateParamsTest { + + @Test + fun create() { + PetUpdateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + PetUpdateParams.builder() + .pet( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = + PetUpdateParams.builder() + .pet(Pet.builder().name("doggie").addPhotoUrl("string").build()) + .build() + + val body = params._body() + + assertThat(body).isEqualTo(Pet.builder().name("doggie").addPhotoUrl("string").build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParamsTest.kt new file mode 100644 index 0000000..05542ba --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageParamsTest.kt @@ -0,0 +1,77 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUploadImageParamsTest { + + @Test + fun create() { + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + } + + @Test + fun pathParams() { + val params = PetUploadImageParams.builder().petId(0L).image("some content").build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun queryParams() { + val params = + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder().put("additionalMetadata", "additionalMetadata").build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = PetUploadImageParams.builder().petId(0L).image("some content").build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } + + @Test + fun body() { + val params = + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + + val body = params._body() + + assertThat(body).isEqualTo("some content") + } + + @Test + fun bodyWithoutOptionalFields() { + val params = PetUploadImageParams.builder().petId(0L).image("some content").build() + + val body = params._body() + + assertThat(body).isEqualTo("some content") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponseTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponseTest.kt new file mode 100644 index 0000000..e3887f5 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/pets/PetUploadImageResponseTest.kt @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.pets + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class PetUploadImageResponseTest { + + @Test + fun create() { + val petUploadImageResponse = + PetUploadImageResponse.builder().code(0).message("message").type("type").build() + + assertThat(petUploadImageResponse.code()).isEqualTo(0) + assertThat(petUploadImageResponse.message()).isEqualTo("message") + assertThat(petUploadImageResponse.type()).isEqualTo("type") + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val petUploadImageResponse = + PetUploadImageResponse.builder().code(0).message("message").type("type").build() + + val roundtrippedPetUploadImageResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(petUploadImageResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedPetUploadImageResponse).isEqualTo(petUploadImageResponse) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParamsTest.kt new file mode 100644 index 0000000..34f9383 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryParamsTest.kt @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import org.junit.jupiter.api.Test + +internal class StoreListInventoryParamsTest { + + @Test + fun create() { + StoreListInventoryParams.builder().build() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponseTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponseTest.kt new file mode 100644 index 0000000..d27c18e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/StoreListInventoryResponseTest.kt @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class StoreListInventoryResponseTest { + + @Test + fun create() { + val storeListInventoryResponse = + StoreListInventoryResponse.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val storeListInventoryResponse = + StoreListInventoryResponse.builder() + .putAdditionalProperty("foo", JsonValue.from(0)) + .build() + + val roundtrippedStoreListInventoryResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(storeListInventoryResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedStoreListInventoryResponse).isEqualTo(storeListInventoryResponse) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParamsTest.kt new file mode 100644 index 0000000..9f13f41 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderCreateParamsTest.kt @@ -0,0 +1,65 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderCreateParamsTest { + + @Test + fun create() { + OrderCreateParams.builder() + .order( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + OrderCreateParams.builder() + .order( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = OrderCreateParams.builder().build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParamsTest.kt new file mode 100644 index 0000000..02c82b9 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderDeleteParamsTest { + + @Test + fun create() { + OrderDeleteParams.builder().orderId(0L).build() + } + + @Test + fun pathParams() { + val params = OrderDeleteParams.builder().orderId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParamsTest.kt new file mode 100644 index 0000000..c7d569e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/store/orders/OrderRetrieveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.store.orders + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class OrderRetrieveParamsTest { + + @Test + fun create() { + OrderRetrieveParams.builder().orderId(0L).build() + } + + @Test + fun pathParams() { + val params = OrderRetrieveParams.builder().orderId(0L).build() + + assertThat(params._pathParam(0)).isEqualTo("0") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParamsTest.kt new file mode 100644 index 0000000..36afa09 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateParamsTest.kt @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserCreateParamsTest { + + @Test + fun create() { + UserCreateParams.builder() + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + UserCreateParams.builder() + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = UserCreateParams.builder().build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParamsTest.kt new file mode 100644 index 0000000..f5a7cdc --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserCreateWithListParamsTest.kt @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserCreateWithListParamsTest { + + @Test + fun create() { + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + } + + @Test + fun body() { + val params = + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .containsExactly( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = UserCreateWithListParams.builder().build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParamsTest.kt new file mode 100644 index 0000000..5c6f200 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserDeleteParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserDeleteParamsTest { + + @Test + fun create() { + UserDeleteParams.builder().username("username").build() + } + + @Test + fun pathParams() { + val params = UserDeleteParams.builder().username("username").build() + + assertThat(params._pathParam(0)).isEqualTo("username") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParamsTest.kt new file mode 100644 index 0000000..3863669 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLoginParamsTest.kt @@ -0,0 +1,39 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.pioneer_intergration_app.api.core.http.QueryParams +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserLoginParamsTest { + + @Test + fun create() { + UserLoginParams.builder().password("password").username("username").build() + } + + @Test + fun queryParams() { + val params = UserLoginParams.builder().password("password").username("username").build() + + val queryParams = params._queryParams() + + assertThat(queryParams) + .isEqualTo( + QueryParams.builder() + .put("password", "password") + .put("username", "username") + .build() + ) + } + + @Test + fun queryParamsWithoutOptionalFields() { + val params = UserLoginParams.builder().build() + + val queryParams = params._queryParams() + + assertThat(queryParams).isEqualTo(QueryParams.builder().build()) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParamsTest.kt new file mode 100644 index 0000000..bcbdd1c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserLogoutParamsTest.kt @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.junit.jupiter.api.Test + +internal class UserLogoutParamsTest { + + @Test + fun create() { + UserLogoutParams.builder().build() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParamsTest.kt new file mode 100644 index 0000000..6ac07d9 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserRetrieveParamsTest.kt @@ -0,0 +1,23 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserRetrieveParamsTest { + + @Test + fun create() { + UserRetrieveParams.builder().username("username").build() + } + + @Test + fun pathParams() { + val params = UserRetrieveParams.builder().username("username").build() + + assertThat(params._pathParam(0)).isEqualTo("username") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserTest.kt new file mode 100644 index 0000000..9932c8a --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserTest.kt @@ -0,0 +1,56 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.core.jsonMapper +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserTest { + + @Test + fun create() { + val user = + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + + assertThat(user.id()).isEqualTo(10L) + assertThat(user.email()).isEqualTo("john@email.com") + assertThat(user.firstName()).isEqualTo("John") + assertThat(user.lastName()).isEqualTo("James") + assertThat(user.password()).isEqualTo("12345") + assertThat(user.phone()).isEqualTo("12345") + assertThat(user.username()).isEqualTo("theUser") + assertThat(user.userStatus()).isEqualTo(1) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val user = + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + + val roundtrippedUser = + jsonMapper.readValue(jsonMapper.writeValueAsString(user), jacksonTypeRef()) + + assertThat(roundtrippedUser).isEqualTo(user) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParamsTest.kt new file mode 100644 index 0000000..52d4868 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/models/users/UserUpdateParamsTest.kt @@ -0,0 +1,80 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.models.users + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class UserUpdateParamsTest { + + @Test + fun create() { + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + } + + @Test + fun pathParams() { + val params = UserUpdateParams.builder().existingUsername("username").build() + + assertThat(params._pathParam(0)).isEqualTo("username") + // out-of-bound path param + assertThat(params._pathParam(1)).isEqualTo("") + } + + @Test + fun body() { + val params = + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + + val body = params._body() + + assertThat(body) + .isEqualTo( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + } + + @Test + fun bodyWithoutOptionalFields() { + val params = UserUpdateParams.builder().existingUsername("username").build() + + val body = params._body() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ErrorHandlingTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ErrorHandlingTest.kt new file mode 100644 index 0000000..b1b41e6 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ErrorHandlingTest.kt @@ -0,0 +1,349 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services + +import com.github.tomakehurst.wiremock.client.WireMock.anyUrl +import com.github.tomakehurst.wiremock.client.WireMock.get +import com.github.tomakehurst.wiremock.client.WireMock.status +import com.github.tomakehurst.wiremock.client.WireMock.stubFor +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.core.JsonValue +import com.pioneer_intergration_app.api.core.http.Headers +import com.pioneer_intergration_app.api.core.jsonMapper +import com.pioneer_intergration_app.api.errors.BadRequestException +import com.pioneer_intergration_app.api.errors.InternalServerException +import com.pioneer_intergration_app.api.errors.NotFoundException +import com.pioneer_intergration_app.api.errors.PermissionDeniedException +import com.pioneer_intergration_app.api.errors.PioneerIntergrationAppException +import com.pioneer_intergration_app.api.errors.RateLimitException +import com.pioneer_intergration_app.api.errors.UnauthorizedException +import com.pioneer_intergration_app.api.errors.UnexpectedStatusCodeException +import com.pioneer_intergration_app.api.errors.UnprocessableEntityException +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.entry +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.api.parallel.ResourceLock + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class ErrorHandlingTest { + + companion object { + + private val ERROR_JSON: JsonValue = JsonValue.from(mapOf("errorProperty" to "42")) + + private val ERROR_JSON_BYTES: ByteArray = jsonMapper().writeValueAsBytes(ERROR_JSON) + + private const val HEADER_NAME: String = "Error-Header" + + private const val HEADER_VALUE: String = "42" + + private const val NOT_JSON: String = "Not JSON" + } + + private lateinit var client: PioneerIntergrationAppClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(wmRuntimeInfo.httpBaseUrl) + .apiKey("My API Key") + .build() + } + + @Test + fun storeListInventory400() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(400).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(400) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory400WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(400).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(400) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory401() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(401).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(401) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory401WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(401).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(401) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory403() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(403).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(403) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory403WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(403).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(403) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory404() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(404).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(404) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory404WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(404).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(404) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory422() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(422).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(422) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory422WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(422).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(422) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory429() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(429).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(429) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory429WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(429).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(429) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory500() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(500).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(500) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory500WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(500).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(500) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory999() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn( + status(999).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(999) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventory999WithRawResponse() { + val storeService = client.store().withRawResponse() + stubFor( + get(anyUrl()) + .willReturn( + status(999).withHeader(HEADER_NAME, HEADER_VALUE).withBody(ERROR_JSON_BYTES) + ) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e.statusCode()).isEqualTo(999) + assertThat(e.headers().toMap()).contains(entry(HEADER_NAME, listOf(HEADER_VALUE))) + assertThat(e.body()).isEqualTo(ERROR_JSON) + } + + @Test + fun storeListInventoryInvalidJsonBody() { + val storeService = client.store() + stubFor( + get(anyUrl()) + .willReturn(status(200).withHeader(HEADER_NAME, HEADER_VALUE).withBody(NOT_JSON)) + ) + + val e = assertThrows { storeService.listInventory() } + + assertThat(e).hasMessage("Error reading response") + } + + private fun Headers.toMap(): Map> = + mutableMapOf>().also { map -> + names().forEach { map[it] = values(it) } + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt new file mode 100644 index 0000000..d73658e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt @@ -0,0 +1,84 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services + +import com.github.tomakehurst.wiremock.client.WireMock.anyUrl +import com.github.tomakehurst.wiremock.client.WireMock.equalTo +import com.github.tomakehurst.wiremock.client.WireMock.get +import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor +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.stubFor +import com.github.tomakehurst.wiremock.client.WireMock.verify +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo +import com.github.tomakehurst.wiremock.junit5.WireMockTest +import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import java.time.OffsetDateTime +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.parallel.ResourceLock + +@WireMockTest +@ResourceLock("https://github.com/wiremock/wiremock/issues/169") +internal class ServiceParamsTest { + + private lateinit var client: PioneerIntergrationAppClient + + @BeforeEach + fun beforeEach(wmRuntimeInfo: WireMockRuntimeInfo) { + client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(wmRuntimeInfo.httpBaseUrl) + .apiKey("My API Key") + .build() + } + + @Disabled("Prism tests are disabled") + @Test + fun listInventory() { + val storeService = client.store() + stubFor(get(anyUrl()).willReturn(ok("{}"))) + + storeService.listInventory( + StoreListInventoryParams.builder() + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") + .build() + ) + + verify( + getRequestedFor(anyUrl()) + .withHeader("Secret-Header", equalTo("42")) + .withQueryParam("secret_query_param", equalTo("42")) + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val orderService = client.store().orders() + stubFor(post(anyUrl()).willReturn(ok("{}"))) + + orderService.create( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + + verify( + postRequestedFor(anyUrl()) + .withHeader("Secret-Header", equalTo("42")) + .withQueryParam("secret_query_param", equalTo("42")) + ) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncTest.kt new file mode 100644 index 0000000..e5b8172 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/PetServiceAsyncTest.kt @@ -0,0 +1,170 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.pets.Category +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class PetServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun create() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pet = + petServiceAsync.create( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pet = petServiceAsync.retrieve(0L) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun update() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pet = + petServiceAsync.update( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun delete() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + petServiceAsync.delete(0L) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun findByStatus() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pets = + petServiceAsync.findByStatus( + PetFindByStatusParams.builder() + .status(PetFindByStatusParams.Status.AVAILABLE) + .build() + ) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun findByTags() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val pets = + petServiceAsync.findByTags(PetFindByTagsParams.builder().addTag("string").build()) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun updateById() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + petServiceAsync.updateById( + PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun uploadImage() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petServiceAsync = client.pets() + + val response = + petServiceAsync.uploadImage( + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + ) + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncTest.kt new file mode 100644 index 0000000..155b063 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/StoreServiceAsyncTest.kt @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class StoreServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun listInventory() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val storeServiceAsync = client.store() + + val response = storeServiceAsync.listInventory() + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncTest.kt new file mode 100644 index 0000000..a475abb --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/UserServiceAsyncTest.kt @@ -0,0 +1,160 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class UserServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun create() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + val user = + userServiceAsync.create( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + val user = userServiceAsync.retrieve("username") + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun update() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.update( + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun delete() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.delete("username") + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun createWithList() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + val user = + userServiceAsync.createWithList( + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun login() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.login( + UserLoginParams.builder().password("password").username("username").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun logout() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userServiceAsync = client.users() + + userServiceAsync.logout() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncTest.kt new file mode 100644 index 0000000..59b155c --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/async/store/OrderServiceAsyncTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.async.store + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClientAsync +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class OrderServiceAsyncTest { + + @Disabled("Prism tests are disabled") + @Test + suspend fun create() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderServiceAsync = client.store().orders() + + val order = + orderServiceAsync.create( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderServiceAsync = client.store().orders() + + val order = orderServiceAsync.retrieve(0L) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + suspend fun delete() { + val client = + PioneerIntergrationAppOkHttpClientAsync.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderServiceAsync = client.store().orders() + + orderServiceAsync.delete(0L) + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceTest.kt new file mode 100644 index 0000000..9fb4f5e --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/PetServiceTest.kt @@ -0,0 +1,169 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.pets.Category +import com.pioneer_intergration_app.api.models.pets.Pet +import com.pioneer_intergration_app.api.models.pets.PetFindByStatusParams +import com.pioneer_intergration_app.api.models.pets.PetFindByTagsParams +import com.pioneer_intergration_app.api.models.pets.PetUpdateByIdParams +import com.pioneer_intergration_app.api.models.pets.PetUploadImageParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class PetServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pet = + petService.create( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pet = petService.retrieve(0L) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun update() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pet = + petService.update( + Pet.builder() + .name("doggie") + .addPhotoUrl("string") + .id(10L) + .category(Category.builder().id(1L).name("Dogs").build()) + .status(Pet.Status.AVAILABLE) + .addTag(Pet.Tag.builder().id(0L).name("name").build()) + .build() + ) + + pet.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun delete() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + petService.delete(0L) + } + + @Disabled("Prism tests are disabled") + @Test + fun findByStatus() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pets = + petService.findByStatus( + PetFindByStatusParams.builder() + .status(PetFindByStatusParams.Status.AVAILABLE) + .build() + ) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + fun findByTags() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val pets = petService.findByTags(PetFindByTagsParams.builder().addTag("string").build()) + + pets.forEach { it.validate() } + } + + @Disabled("Prism tests are disabled") + @Test + fun updateById() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + petService.updateById( + PetUpdateByIdParams.builder().petId(0L).name("name").status("status").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun uploadImage() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val petService = client.pets() + + val response = + petService.uploadImage( + PetUploadImageParams.builder() + .petId(0L) + .additionalMetadata("additionalMetadata") + .image("some content") + .build() + ) + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceTest.kt new file mode 100644 index 0000000..b0acf06 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/StoreServiceTest.kt @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class StoreServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun listInventory() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val storeService = client.store() + + val response = storeService.listInventory() + + response.validate() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceTest.kt new file mode 100644 index 0000000..0e0ff55 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/UserServiceTest.kt @@ -0,0 +1,160 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.users.User +import com.pioneer_intergration_app.api.models.users.UserCreateWithListParams +import com.pioneer_intergration_app.api.models.users.UserLoginParams +import com.pioneer_intergration_app.api.models.users.UserUpdateParams +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class UserServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + val user = + userService.create( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + val user = userService.retrieve("username") + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun update() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.update( + UserUpdateParams.builder() + .existingUsername("username") + .user( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun delete() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.delete("username") + } + + @Disabled("Prism tests are disabled") + @Test + fun createWithList() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + val user = + userService.createWithList( + UserCreateWithListParams.builder() + .addItem( + User.builder() + .id(10L) + .email("john@email.com") + .firstName("John") + .lastName("James") + .password("12345") + .phone("12345") + .username("theUser") + .userStatus(1) + .build() + ) + .build() + ) + + user.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun login() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.login( + UserLoginParams.builder().password("password").username("username").build() + ) + } + + @Disabled("Prism tests are disabled") + @Test + fun logout() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val userService = client.users() + + userService.logout() + } +} diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceTest.kt new file mode 100644 index 0000000..b907022 --- /dev/null +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/blocking/store/OrderServiceTest.kt @@ -0,0 +1,68 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.services.blocking.store + +import com.pioneer_intergration_app.api.TestServerExtension +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestServerExtension::class) +internal class OrderServiceTest { + + @Disabled("Prism tests are disabled") + @Test + fun create() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderService = client.store().orders() + + val order = + orderService.create( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun retrieve() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderService = client.store().orders() + + val order = orderService.retrieve(0L) + + order.validate() + } + + @Disabled("Prism tests are disabled") + @Test + fun delete() { + val client = + PioneerIntergrationAppOkHttpClient.builder() + .baseUrl(TestServerExtension.BASE_URL) + .apiKey("My API Key") + .build() + val orderService = client.store().orders() + + orderService.delete(0L) + } +} diff --git a/pioneer-intergration-app-kotlin-example/build.gradle.kts b/pioneer-intergration-app-kotlin-example/build.gradle.kts new file mode 100644 index 0000000..0af57b1 --- /dev/null +++ b/pioneer-intergration-app-kotlin-example/build.gradle.kts @@ -0,0 +1,19 @@ +plugins { + id("pioneer-intergration-app.kotlin") + application +} + +dependencies { + implementation(project(":pioneer-intergration-app-kotlin")) +} + +application { + // Use `./gradlew :pioneer-intergration-app-kotlin-example:run` to run `Main` + // Use `./gradlew :pioneer-intergration-app-kotlin-example:run -Pexample=Something` to run `SomethingExample` + mainClass = "com.pioneer_intergration_app.api.example.${ + if (project.hasProperty("example")) + "${project.property("example")}ExampleKt" + else + "MainKt" + }" +} diff --git a/pioneer-intergration-app-kotlin-lib/.keep b/pioneer-intergration-app-kotlin-lib/.keep new file mode 100644 index 0000000..5e2c99f --- /dev/null +++ b/pioneer-intergration-app-kotlin-lib/.keep @@ -0,0 +1,4 @@ +File generated from our OpenAPI spec by Stainless. + +This directory can be used to store custom files to expand the SDK. +It is ignored by Stainless code generation and its content (other than this keep file) won't be touched. \ No newline at end of file diff --git a/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts new file mode 100644 index 0000000..fc67fcc --- /dev/null +++ b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts @@ -0,0 +1,101 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("com.gradleup.shadow") version "8.3.8" +} + +buildscript { + repositories { + google() + } + + dependencies { + classpath("com.guardsquare:proguard-gradle:7.4.2") + classpath("com.android.tools:r8:8.3.37") + } +} + +dependencies { + testImplementation(project(":pioneer-intergration-app-kotlin")) + testImplementation(kotlin("test")) + testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") + testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") +} + +tasks.shadowJar { + from(sourceSets.test.get().output) + configurations = listOf(project.configurations.testRuntimeClasspath.get()) +} + +val proguardJarPath = "${layout.buildDirectory.get()}/libs/${project.name}-${project.version}-proguard.jar" +val proguardJar by tasks.registering(proguard.gradle.ProGuardTask::class) { + group = "verification" + dependsOn(tasks.shadowJar) + notCompatibleWithConfigurationCache("ProGuard") + + injars(tasks.shadowJar) + outjars(proguardJarPath) + printmapping("${layout.buildDirectory.get()}/proguard-mapping.txt") + + val javaHome = System.getProperty("java.home") + if (System.getProperty("java.version").startsWith("1.")) { + // Before Java 9, the runtime classes were packaged in a single jar file. + libraryjars("$javaHome/lib/rt.jar") + } else { + // As of Java 9, the runtime classes are packaged in modular jmod files. + libraryjars( + // Filters must be specified first, as a map. + mapOf("jarfilter" to "!**.jar", "filter" to "!module-info.class"), + "$javaHome/jmods/java.base.jmod" + ) + } + + configuration("./test.pro") + configuration("../pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro") +} + +val testProGuard by tasks.registering(JavaExec::class) { + group = "verification" + dependsOn(proguardJar) + notCompatibleWithConfigurationCache("ProGuard") + + mainClass.set("com.pioneer_intergration_app.api.proguard.ProGuardCompatibilityTest") + classpath = files(proguardJarPath) +} + +val r8JarPath = "${layout.buildDirectory.get()}/libs/${project.name}-${project.version}-r8.jar" +val r8Jar by tasks.registering(JavaExec::class) { + group = "verification" + dependsOn(tasks.shadowJar) + notCompatibleWithConfigurationCache("R8") + + mainClass.set("com.android.tools.r8.R8") + classpath = buildscript.configurations["classpath"] + + args = listOf( + "--release", + "--classfile", + "--output", r8JarPath, + "--lib", System.getProperty("java.home"), + "--pg-conf", "./test.pro", + "--pg-conf", "../pioneer-intergration-app-kotlin-core/src/main/resources/META-INF/proguard/pioneer-intergration-app-kotlin-core.pro", + "--pg-map-output", "${layout.buildDirectory.get()}/r8-mapping.txt", + tasks.shadowJar.get().archiveFile.get().asFile.absolutePath, + ) +} + +val testR8 by tasks.registering(JavaExec::class) { + group = "verification" + dependsOn(r8Jar) + notCompatibleWithConfigurationCache("R8") + + mainClass.set("com.pioneer_intergration_app.api.proguard.ProGuardCompatibilityTest") + classpath = files(r8JarPath) +} + +tasks.test { + dependsOn(testProGuard) + dependsOn(testR8) + // We defer to the tests run via the ProGuard JAR. + enabled = false +} diff --git a/pioneer-intergration-app-kotlin-proguard-test/src/test/kotlin/com/pioneer_intergration_app/api/proguard/ProGuardCompatibilityTest.kt b/pioneer-intergration-app-kotlin-proguard-test/src/test/kotlin/com/pioneer_intergration_app/api/proguard/ProGuardCompatibilityTest.kt new file mode 100644 index 0000000..07d0682 --- /dev/null +++ b/pioneer-intergration-app-kotlin-proguard-test/src/test/kotlin/com/pioneer_intergration_app/api/proguard/ProGuardCompatibilityTest.kt @@ -0,0 +1,76 @@ +// File generated from our OpenAPI spec by Stainless. + +package com.pioneer_intergration_app.api.proguard + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient +import com.pioneer_intergration_app.api.core.jsonMapper +import com.pioneer_intergration_app.api.models.Order +import java.time.OffsetDateTime +import kotlin.reflect.full.memberFunctions +import kotlin.reflect.jvm.javaMethod +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class ProGuardCompatibilityTest { + + companion object { + + @JvmStatic + fun main(args: Array) { + // To debug that we're using the right JAR. + val jarPath = this::class.java.getProtectionDomain().codeSource.location + println("JAR being used: $jarPath") + + // We have to manually run the test methods instead of using the JUnit runner because it + // seems impossible to get working with R8. + val test = ProGuardCompatibilityTest() + test::class + .memberFunctions + .asSequence() + .filter { function -> + function.javaMethod?.isAnnotationPresent(Test::class.java) == true + } + .forEach { it.call(test) } + } + } + + @Test + fun proguardRules() { + val rulesFile = + javaClass.classLoader.getResourceAsStream( + "META-INF/proguard/pioneer-intergration-app-kotlin-core.pro" + ) + + assertThat(rulesFile).isNotNull() + } + + @Test + fun client() { + val client = PioneerIntergrationAppOkHttpClient.builder().apiKey("My API Key").build() + + assertThat(client).isNotNull() + assertThat(client.pets()).isNotNull() + assertThat(client.store()).isNotNull() + assertThat(client.users()).isNotNull() + } + + @Test + fun orderRoundtrip() { + val jsonMapper = jsonMapper() + val order = + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + + val roundtrippedOrder = + jsonMapper.readValue(jsonMapper.writeValueAsString(order), jacksonTypeRef()) + + assertThat(roundtrippedOrder).isEqualTo(order) + } +} diff --git a/pioneer-intergration-app-kotlin-proguard-test/test.pro b/pioneer-intergration-app-kotlin-proguard-test/test.pro new file mode 100644 index 0000000..ef5edfc --- /dev/null +++ b/pioneer-intergration-app-kotlin-proguard-test/test.pro @@ -0,0 +1,9 @@ +# Specify the entrypoint where ProGuard starts to determine what's reachable. +-keep class com.pioneer_intergration_app.api.proguard.** { *; } + +# For the testing framework. +-keep class org.junit.** { *; } + +# Many warnings don't apply for our testing purposes. +-dontnote +-dontwarn \ No newline at end of file diff --git a/pioneer-intergration-app-kotlin/build.gradle.kts b/pioneer-intergration-app-kotlin/build.gradle.kts new file mode 100644 index 0000000..9f7acb1 --- /dev/null +++ b/pioneer-intergration-app-kotlin/build.gradle.kts @@ -0,0 +1,29 @@ +plugins { + id("pioneer-intergration-app.kotlin") + id("pioneer-intergration-app.publish") +} + +dependencies { + api(project(":pioneer-intergration-app-kotlin-client-okhttp")) +} + +// Redefine `dokkaHtml` to: +// - Depend on the root project's task for merging the docs of all the projects +// - Forward that task's output to this task's output +tasks.named("dokkaHtml").configure { + actions.clear() + + val dokkaHtmlCollector = rootProject.tasks["dokkaHtmlCollector"] + dependsOn(dokkaHtmlCollector) + + val outputDirectory = project.layout.buildDirectory.dir("dokka/html") + doLast { + copy { + from(dokkaHtmlCollector.outputs.files) + into(outputDirectory) + duplicatesStrategy = DuplicatesStrategy.INCLUDE + } + } + + outputs.dir(outputDirectory) +} diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..8f98719 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,67 @@ +{ + "packages": { + ".": {} + }, + "$schema": "https://raw.githubusercontent.com/stainless-api/release-please/main/schemas/config.json", + "include-v-in-tag": true, + "include-component-in-tag": false, + "versioning": "prerelease", + "prerelease": true, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "perf", + "section": "Performance Improvements" + }, + { + "type": "revert", + "section": "Reverts" + }, + { + "type": "chore", + "section": "Chores" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "style", + "section": "Styles" + }, + { + "type": "refactor", + "section": "Refactors" + }, + { + "type": "test", + "section": "Tests", + "hidden": true + }, + { + "type": "build", + "section": "Build System" + }, + { + "type": "ci", + "section": "Continuous Integration", + "hidden": true + } + ], + "release-type": "simple", + "extra-files": [ + "README.md", + "build.gradle.kts" + ] +} \ No newline at end of file diff --git a/scripts/build b/scripts/build new file mode 100755 index 0000000..f406348 --- /dev/null +++ b/scripts/build @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +echo "==> Building classes" +./gradlew build testClasses -x test diff --git a/scripts/format b/scripts/format new file mode 100755 index 0000000..9e294b9 --- /dev/null +++ b/scripts/format @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if command -v ktfmt &> /dev/null; then + echo "==> Running ktfmt" + find . -name "*.kt" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r ktfmt --kotlinlang-style "$@" +else + echo "==> Running gradlew format" + ./gradlew format +fi diff --git a/scripts/lint b/scripts/lint new file mode 100755 index 0000000..5837798 --- /dev/null +++ b/scripts/lint @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if command -v ktfmt &> /dev/null; then + echo "==> Checking ktfmt" + ./scripts/format --dry-run --set-exit-if-changed +else + echo "==> Running gradlew lint" + ./gradlew lint +fi diff --git a/scripts/mock b/scripts/mock new file mode 100755 index 0000000..0b28f6e --- /dev/null +++ b/scripts/mock @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +if [[ -n "$1" && "$1" != '--'* ]]; then + URL="$1" + shift +else + URL="$(grep 'openapi_spec_url' .stats.yml | cut -d' ' -f2)" +fi + +# Check if the URL is empty +if [ -z "$URL" ]; then + echo "Error: No OpenAPI spec path/url provided or found in .stats.yml" + exit 1 +fi + +echo "==> Starting mock server with URL ${URL}" + +# Run prism mock on the given spec +if [ "$1" == "--daemon" ]; then + npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock "$URL" &> .prism.log & + + # Wait for server to come online + echo -n "Waiting for server" + while ! grep -q "✖ fatal\|Prism is listening" ".prism.log" ; do + 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" +fi diff --git a/scripts/test b/scripts/test new file mode 100755 index 0000000..047bc1d --- /dev/null +++ b/scripts/test @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +RED='\033[0;31m' +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 +} + +kill_server_on_port() { + pids=$(lsof -t -i tcp:"$1" || echo "") + if [ "$pids" != "" ]; then + kill "$pids" + echo "Stopped $pids." + fi +} + +function is_overriding_api_base_url() { + [ -n "$TEST_API_BASE_URL" ] +} + +if ! is_overriding_api_base_url && ! prism_is_running ; then + # When we exit this script, make sure to kill the background mock server process + trap 'kill_server_on_port 4010' EXIT + + # Start the dev server + ./scripts/mock --daemon +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" + 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 + echo -e " \$ ${YELLOW}npm exec --package=@stainless-api/prism-cli@5.15.0 -- prism mock path/to/your.openapi.yml${NC}" + echo + + exit 1 +else + echo -e "${GREEN}✔ Mock prism server is running with your OpenAPI spec${NC}" + echo +fi + +echo "==> Running tests" +./gradlew test "$@" diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..6f6df7e --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,14 @@ +rootProject.name = "pioneer-intergration-app-kotlin-root" + +val projectNames = rootDir.listFiles() + ?.asSequence() + .orEmpty() + .filter { file -> + file.isDirectory && + file.name.startsWith("pioneer-intergration-app-kotlin") && + file.listFiles()?.asSequence().orEmpty().any { it.name == "build.gradle.kts" } + } + .map { it.name } + .toList() +println("projects: $projectNames") +projectNames.forEach { include(it) } From d64728faddd00d52ea2a33faae5453966524c9cb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 15:31:36 +0000 Subject: [PATCH 02/24] chore: update SDK settings --- .github/workflows/release-doctor.yml | 2 +- .stats.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index f7ff40c..59788d6 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -2,7 +2,7 @@ name: Release Doctor on: pull_request: branches: - - main + - master workflow_dispatch: jobs: diff --git a/.stats.yml b/.stats.yml index c040c03..4fbfbe4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 -config_hash: 6d70aedc8c7eb71038c9cebef29eb95d +config_hash: bbb379c83a14b5543bd8e1734dd2d1c6 From ee5ba122373a91853a02f648e2d79f3fa5c4ad27 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 9 Jan 2026 06:55:18 +0000 Subject: [PATCH 03/24] feat(client): allow configuring dispatcher executor service --- .../api/client/okhttp/OkHttpClient.kt | 9 +++++++++ .../okhttp/PioneerIntergrationAppOkHttpClient.kt | 15 +++++++++++++++ .../PioneerIntergrationAppOkHttpClientAsync.kt | 15 +++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt index d10caae..010d563 100644 --- a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt @@ -13,12 +13,14 @@ import java.io.IOException import java.io.InputStream import java.net.Proxy import java.time.Duration +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager import kotlinx.coroutines.suspendCancellableCoroutine import okhttp3.Call import okhttp3.Callback +import okhttp3.Dispatcher import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType @@ -200,6 +202,7 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC private var timeout: Timeout = Timeout.default() private var proxy: Proxy? = null + private var dispatcherExecutorService: ExecutorService? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null @@ -210,6 +213,10 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + fun sslSocketFactory(sslSocketFactory: SSLSocketFactory?) = apply { this.sslSocketFactory = sslSocketFactory } @@ -231,6 +238,8 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC .callTimeout(timeout.request()) .proxy(proxy) .apply { + dispatcherExecutorService?.let { dispatcher(Dispatcher(it)) } + val sslSocketFactory = sslSocketFactory val trustManager = trustManager if (sslSocketFactory != null && trustManager != null) { diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt index b225e43..8bc4fa6 100644 --- a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClient.kt @@ -15,6 +15,7 @@ import com.pioneer_intergration_app.api.core.jsonMapper import java.net.Proxy import java.time.Clock import java.time.Duration +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -44,11 +45,24 @@ class PioneerIntergrationAppOkHttpClient private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** @@ -278,6 +292,7 @@ class PioneerIntergrationAppOkHttpClient private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt index df9934e..77fdad5 100644 --- a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/PioneerIntergrationAppOkHttpClientAsync.kt @@ -15,6 +15,7 @@ import com.pioneer_intergration_app.api.core.jsonMapper import java.net.Proxy import java.time.Clock import java.time.Duration +import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory import javax.net.ssl.X509TrustManager @@ -45,11 +46,24 @@ class PioneerIntergrationAppOkHttpClientAsync private constructor() { class Builder internal constructor() { private var clientOptions: ClientOptions.Builder = ClientOptions.builder() + private var dispatcherExecutorService: ExecutorService? = null private var proxy: Proxy? = null private var sslSocketFactory: SSLSocketFactory? = null private var trustManager: X509TrustManager? = null private var hostnameVerifier: HostnameVerifier? = null + /** + * The executor service to use for running HTTP requests. + * + * Defaults to OkHttp's + * [default executor service](https://github.com/square/okhttp/blob/ace792f443b2ffb17974f5c0d1cecdf589309f26/okhttp/src/commonJvmAndroid/kotlin/okhttp3/Dispatcher.kt#L98-L104). + * + * This class takes ownership of the executor service and shuts it down when closed. + */ + fun dispatcherExecutorService(dispatcherExecutorService: ExecutorService?) = apply { + this.dispatcherExecutorService = dispatcherExecutorService + } + fun proxy(proxy: Proxy?) = apply { this.proxy = proxy } /** @@ -279,6 +293,7 @@ class PioneerIntergrationAppOkHttpClientAsync private constructor() { OkHttpClient.builder() .timeout(clientOptions.timeout()) .proxy(proxy) + .dispatcherExecutorService(dispatcherExecutorService) .sslSocketFactory(sslSocketFactory) .trustManager(trustManager) .hostnameVerifier(hostnameVerifier) From 07af80a3aea53084d0291e9e0d8e09f13b5b27e9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 12 Jan 2026 04:00:51 +0000 Subject: [PATCH 04/24] chore(internal): codegen related update --- .DS_Store | Bin 0 -> 6162 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8d0676f575d2fd605b438b5300b0baa7d72a2d16 GIT binary patch literal 6162 zcmeHK!Ab)`41Lia3SN2?PxA}@!CJN_FT#F+idGS8mC_b}PW&W)!Iw-HwCkZaL0=$w zlbK9r_rY!^0BpLsJq0EJ##BdqyuUdN#Uoq?a*#7dq%z9|u5p7$+WSHD&lA4)1RYwO zEu)uuVt(J@DrJv(DBw|1ehygJm2E@RA3}oFLAMF>e zC@~-g{t*NIe<)PPCb4!2obgFF(F71j?z?at{RFY3-y~*>VRbWY?I0{STecZi6L38e z5F-Jx?@^4&U92X6<>{7vip3Lfy)cMkO@NFT5Cc0599Dngw}2V7|HgL0 Date: Mon, 12 Jan 2026 04:03:13 +0000 Subject: [PATCH 05/24] chore(internal): codegen related update --- .DS_Store | Bin 6162 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 8d0676f575d2fd605b438b5300b0baa7d72a2d16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6162 zcmeHK!Ab)`41Lia3SN2?PxA}@!CJN_FT#F+idGS8mC_b}PW&W)!Iw-HwCkZaL0=$w zlbK9r_rY!^0BpLsJq0EJ##BdqyuUdN#Uoq?a*#7dq%z9|u5p7$+WSHD&lA4)1RYwO zEu)uuVt(J@DrJv(DBw|1ehygJm2E@RA3}oFLAMF>e zC@~-g{t*NIe<)PPCb4!2obgFF(F71j?z?at{RFY3-y~*>VRbWY?I0{STecZi6L38e z5F-Jx?@^4&U92X6<>{7vip3Lfy)cMkO@NFT5Cc0599Dngw}2V7|HgL0 Date: Tue, 13 Jan 2026 15:27:38 +0000 Subject: [PATCH 06/24] chore(internal): refactor build files to support future stainless package uploads --- .../kotlin/pioneer-intergration-app.publish.gradle.kts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts index d5c0f65..895938c 100644 --- a/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.publish.gradle.kts @@ -39,6 +39,14 @@ configure { } } } + repositories { + if (project.hasProperty("publishLocal")) { + maven { + name = "LocalFileSystem" + url = uri("${rootProject.layout.buildDirectory.get()}/local-maven-repo") + } + } + } } signing { From e450559d6041ea67c018f05678a12cab3c710253 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 09:20:45 +0000 Subject: [PATCH 07/24] chore: test on Jackson 2.14.0 to avoid encountering FasterXML/jackson-databind#3240 in tests fix: date time deserialization leniency --- README.md | 2 ++ .../build.gradle.kts | 18 +++++----- .../api/core/ObjectMappers.kt | 33 ++++++++++++------- .../api/core/ObjectMappersTest.kt | 16 +++------ .../build.gradle.kts | 2 +- 5 files changed, 38 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index c142d1b..d327ecf 100644 --- a/README.md +++ b/README.md @@ -256,6 +256,8 @@ If the SDK threw an exception, but you're _certain_ the version is compatible, t > [!CAUTION] > We make no guarantee that the SDK works correctly when the Jackson version check is disabled. +Also note that there are bugs in older Jackson versions that can affect the SDK. We don't work around all Jackson bugs ([example](https://github.com/FasterXML/jackson-databind/issues/3240)) and expect users to upgrade Jackson for those instead. + ## Network options ### Retries diff --git a/pioneer-intergration-app-kotlin-core/build.gradle.kts b/pioneer-intergration-app-kotlin-core/build.gradle.kts index 07d1933..a98c04d 100644 --- a/pioneer-intergration-app-kotlin-core/build.gradle.kts +++ b/pioneer-intergration-app-kotlin-core/build.gradle.kts @@ -5,14 +5,16 @@ plugins { configurations.all { resolutionStrategy { - // Compile and test against a lower Jackson version to ensure we're compatible with it. - // We publish with a higher version (see below) to ensure users depend on a secure version by default. - force("com.fasterxml.jackson.core:jackson-core:2.13.4") - force("com.fasterxml.jackson.core:jackson-databind:2.13.4") - force("com.fasterxml.jackson.core:jackson-annotations:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.13.4") - force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.4") - force("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + // Compile and test against a lower Jackson version to ensure we're compatible with it. Note that + // we generally support 2.13.4, but test against 2.14.0 because 2.13.4 has some annoying (but + // niche) bugs (users should upgrade if they encounter them). We publish with a higher version + // (see below) to ensure users depend on a secure version by default. + force("com.fasterxml.jackson.core:jackson-core:2.14.0") + force("com.fasterxml.jackson.core:jackson-databind:2.14.0") + force("com.fasterxml.jackson.core:jackson-annotations:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.0") + force("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.0") + force("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } } diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt index 96a6acf..99bb257 100644 --- a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt @@ -24,6 +24,7 @@ import java.io.InputStream import java.time.DateTimeException import java.time.LocalDate import java.time.LocalDateTime +import java.time.OffsetDateTime import java.time.ZonedDateTime import java.time.format.DateTimeFormatter import java.time.temporal.ChronoField @@ -36,7 +37,7 @@ fun jsonMapper(): JsonMapper = .addModule( SimpleModule() .addSerializer(InputStreamSerializer) - .addDeserializer(LocalDateTime::class.java, LenientLocalDateTimeDeserializer()) + .addDeserializer(OffsetDateTime::class.java, LenientOffsetDateTimeDeserializer()) ) .withCoercionConfig(LogicalType.Boolean) { it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) @@ -64,6 +65,12 @@ fun jsonMapper(): JsonMapper = .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) } + .withCoercionConfig(LogicalType.DateTime) { + it.setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) + } .withCoercionConfig(LogicalType.Array) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail) @@ -124,10 +131,10 @@ private object InputStreamSerializer : BaseSerializer(InputStream:: } /** - * A deserializer that can deserialize [LocalDateTime] from datetimes, dates, and zoned datetimes. + * A deserializer that can deserialize [OffsetDateTime] from datetimes, dates, and zoned datetimes. */ -private class LenientLocalDateTimeDeserializer : - StdDeserializer(LocalDateTime::class.java) { +private class LenientOffsetDateTimeDeserializer : + StdDeserializer(OffsetDateTime::class.java) { companion object { @@ -141,7 +148,7 @@ private class LenientLocalDateTimeDeserializer : override fun logicalType(): LogicalType = LogicalType.DateTime - override fun deserialize(p: JsonParser, context: DeserializationContext?): LocalDateTime { + override fun deserialize(p: JsonParser, context: DeserializationContext): OffsetDateTime { val exceptions = mutableListOf() for (formatter in DATE_TIME_FORMATTERS) { @@ -149,18 +156,20 @@ private class LenientLocalDateTimeDeserializer : val temporal = formatter.parse(p.text) return when { - !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> - LocalDate.from(temporal).atStartOfDay() - !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> - LocalDateTime.from(temporal) - else -> ZonedDateTime.from(temporal).toLocalDateTime() - } + !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> + LocalDate.from(temporal).atStartOfDay() + !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> + LocalDateTime.from(temporal) + else -> ZonedDateTime.from(temporal).toLocalDateTime() + } + .atZone(context.timeZone.toZoneId()) + .toOffsetDateTime() } catch (e: DateTimeException) { exceptions.add(e) } } - throw JsonParseException(p, "Cannot parse `LocalDateTime` from value: ${p.text}").apply { + throw JsonParseException(p, "Cannot parse `OffsetDateTime` from value: ${p.text}").apply { exceptions.forEach { addSuppressed(it) } } } diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt index 7ceb54d..d6ed852 100644 --- a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt @@ -3,7 +3,7 @@ package com.pioneer_intergration_app.api.core import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.readValue -import java.time.LocalDateTime +import java.time.OffsetDateTime import kotlin.reflect.KClass import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.catchThrowable @@ -58,14 +58,6 @@ internal class ObjectMappersTest { LONG to DOUBLE, LONG to INTEGER, CLASS to MAP, - // These aren't actually valid, but coercion configs don't work for String until - // v2.14.0: https://github.com/FasterXML/jackson-databind/issues/3240 - // We currently test on v2.13.4. - BOOLEAN to STRING, - FLOAT to STRING, - DOUBLE to STRING, - INTEGER to STRING, - LONG to STRING, ) } } @@ -84,7 +76,7 @@ internal class ObjectMappersTest { } } - enum class LenientLocalDateTimeTestCase(val string: String) { + enum class LenientOffsetDateTimeTestCase(val string: String) { DATE("1998-04-21"), DATE_TIME("1998-04-21T04:00:00"), ZONED_DATE_TIME_1("1998-04-21T04:00:00+03:00"), @@ -93,10 +85,10 @@ internal class ObjectMappersTest { @ParameterizedTest @EnumSource - fun readLocalDateTime_lenient(testCase: LenientLocalDateTimeTestCase) { + fun readOffsetDateTime_lenient(testCase: LenientOffsetDateTimeTestCase) { val jsonMapper = jsonMapper() val json = jsonMapper.writeValueAsString(testCase.string) - assertDoesNotThrow { jsonMapper().readValue(json) } + assertDoesNotThrow { jsonMapper().readValue(json) } } } diff --git a/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts index fc67fcc..2a3069d 100644 --- a/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts +++ b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts @@ -19,7 +19,7 @@ dependencies { testImplementation(kotlin("test")) testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3") testImplementation("org.assertj:assertj-core:3.25.3") - testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.4") + testImplementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.0") } tasks.shadowJar { From a5b0b70ed6c64a7e964b788429d445fb466fd94f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 09:38:46 +0000 Subject: [PATCH 08/24] fix(client): disallow coercion from float to int --- .../com/pioneer_intergration_app/api/core/ObjectMappers.kt | 1 + .../pioneer_intergration_app/api/core/ObjectMappersTest.kt | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt index 99bb257..a924800 100644 --- a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt @@ -48,6 +48,7 @@ fun jsonMapper(): JsonMapper = } .withCoercionConfig(LogicalType.Integer) { it.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail) + .setCoercion(CoercionInputShape.Float, CoercionAction.Fail) .setCoercion(CoercionInputShape.String, CoercionAction.Fail) .setCoercion(CoercionInputShape.Array, CoercionAction.Fail) .setCoercion(CoercionInputShape.Object, CoercionAction.Fail) diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt index d6ed852..d841d6a 100644 --- a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt @@ -46,11 +46,7 @@ internal class ObjectMappersTest { val VALID_CONVERSIONS = listOf( FLOAT to DOUBLE, - FLOAT to INTEGER, - FLOAT to LONG, DOUBLE to FLOAT, - DOUBLE to INTEGER, - DOUBLE to LONG, INTEGER to FLOAT, INTEGER to DOUBLE, INTEGER to LONG, From cd70de10007c9dda537b1d71cbf1537954f2e0b2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 09:41:12 +0000 Subject: [PATCH 09/24] chore(internal): update `actions/checkout` version --- .github/workflows/ci.yml | 6 +++--- .github/workflows/publish-sonatype.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae73a9a..d661cea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java uses: actions/setup-java@v4 @@ -44,7 +44,7 @@ jobs: if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java uses: actions/setup-java@v4 @@ -67,7 +67,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/pioneer-intergration-app-kotlin' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java uses: actions/setup-java@v4 diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index 0d6e20f..fd97b40 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Java uses: actions/setup-java@v4 diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 59788d6..e748494 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'ummitsmerogers-droid/GetTrustedInstallerShell' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Check release environment run: | From 99fb79e69355202787789110d15615b40a927ce6 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 09:45:36 +0000 Subject: [PATCH 10/24] fix(client): fully respect max retries fix(client): send retry count header for max retries 0 chore(internal): depend on packages directly in example --- .../api/client/okhttp/OkHttpClient.kt | 2 ++ .../api/core/http/RetryingHttpClient.kt | 16 ++++++++-------- .../build.gradle.kts | 3 ++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt index 010d563..6052c9e 100644 --- a/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt +++ b/pioneer-intergration-app-kotlin-client-okhttp/src/main/kotlin/com/pioneer_intergration_app/api/client/okhttp/OkHttpClient.kt @@ -232,6 +232,8 @@ class OkHttpClient private constructor(private val okHttpClient: okhttp3.OkHttpC fun build(): OkHttpClient = OkHttpClient( okhttp3.OkHttpClient.Builder() + // `RetryingHttpClient` handles retries if the user enabled them. + .retryOnConnectionFailure(false) .connectTimeout(timeout.connect()) .readTimeout(timeout.read()) .writeTimeout(timeout.write()) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt index 1b76c92..4a36544 100644 --- a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/http/RetryingHttpClient.kt @@ -29,10 +29,6 @@ private constructor( ) : HttpClient { override fun execute(request: HttpRequest, requestOptions: RequestOptions): HttpResponse { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.execute(request, requestOptions) - } - var modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -46,6 +42,10 @@ private constructor( modifiedRequest = setRetryCountHeader(modifiedRequest, retries) } + if (!isRetryable(modifiedRequest)) { + return httpClient.execute(modifiedRequest, requestOptions) + } + val response = try { val response = httpClient.execute(modifiedRequest, requestOptions) @@ -73,10 +73,6 @@ private constructor( request: HttpRequest, requestOptions: RequestOptions, ): HttpResponse { - if (!isRetryable(request) || maxRetries <= 0) { - return httpClient.executeAsync(request, requestOptions) - } - var modifiedRequest = maybeAddIdempotencyHeader(request) // Don't send the current retry count in the headers if the caller set their own value. @@ -90,6 +86,10 @@ private constructor( modifiedRequest = setRetryCountHeader(modifiedRequest, retries) } + if (!isRetryable(modifiedRequest)) { + return httpClient.executeAsync(modifiedRequest, requestOptions) + } + val response = try { val response = httpClient.execute(modifiedRequest, requestOptions) diff --git a/pioneer-intergration-app-kotlin-example/build.gradle.kts b/pioneer-intergration-app-kotlin-example/build.gradle.kts index 0af57b1..73d669e 100644 --- a/pioneer-intergration-app-kotlin-example/build.gradle.kts +++ b/pioneer-intergration-app-kotlin-example/build.gradle.kts @@ -4,7 +4,8 @@ plugins { } dependencies { - implementation(project(":pioneer-intergration-app-kotlin")) + implementation(project(":pioneer-intergration-app-kotlin-core")) + implementation(project(":pioneer-intergration-app-kotlin-client-okhttp")) } application { From ce82eb8f438a1de87ddba7c944eca968f2b38c9d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 17 Jan 2026 09:47:59 +0000 Subject: [PATCH 11/24] chore(ci): upgrade `actions/setup-java` --- .github/workflows/ci.yml | 6 +++--- .github/workflows/publish-sonatype.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d661cea..e46d9eb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -47,7 +47,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | @@ -70,7 +70,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml index fd97b40..c507f6d 100644 --- a/.github/workflows/publish-sonatype.yml +++ b/.github/workflows/publish-sonatype.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: | From c505efe2a88d8ef73d00eba0a72c64a382ca33f7 Mon Sep 17 00:00:00 2001 From: ummitsmerogers-droid Date: Sat, 17 Jan 2026 08:22:55 -0700 Subject: [PATCH 12/24] Create azure-functions-app-nodejs.yml --- .../workflows/azure-functions-app-nodejs.yml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/azure-functions-app-nodejs.yml diff --git a/.github/workflows/azure-functions-app-nodejs.yml b/.github/workflows/azure-functions-app-nodejs.yml new file mode 100644 index 0000000..cb158eb --- /dev/null +++ b/.github/workflows/azure-functions-app-nodejs.yml @@ -0,0 +1,66 @@ +# This workflow will build a Node.js project and deploy it to an Azure Functions App on Windows or Linux when a commit is pushed to your default branch. +# +# This workflow assumes you have already created the target Azure Functions app. +# For instructions see: +# - https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-node +# - https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-typescript +# +# To configure this workflow: +# 1. Set up the following secrets in your repository: +# - AZURE_FUNCTIONAPP_PUBLISH_PROFILE +# 2. Change env variables for your configuration. +# +# For more information on: +# - GitHub Actions for Azure: https://github.com/Azure/Actions +# - Azure Functions Action: https://github.com/Azure/functions-action +# - Publish Profile: https://github.com/Azure/functions-action#using-publish-profile-as-deployment-credential-recommended +# - Azure Service Principal for RBAC: https://github.com/Azure/functions-action#using-azure-service-principal-for-rbac-as-deployment-credential +# +# For more samples to get started with GitHub Action workflows to deploy to Azure: https://github.com/Azure/actions-workflow-samples/tree/master/FunctionApp + +name: Deploy Node.js project to Azure Function App + +on: + push: + branches: ["main"] + +env: + AZURE_FUNCTIONAPP_NAME: 'your-app-name' # set this to your function app name on Azure + AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your function app project, defaults to the repository root + NODE_VERSION: '20.x' # set this to the node version to use (e.g. '8.x', '10.x', '12.x') + +jobs: + build-and-deploy: + runs-on: windows-latest # For Linux, use ubuntu-latest + environment: dev + steps: + - name: 'Checkout GitHub Action' + uses: actions/checkout@v4 + + # If you want to use Azure RBAC instead of Publish Profile, then uncomment the task below + # - name: 'Login via Azure CLI' + # uses: azure/login@v1 + # with: + # creds: ${{ secrets.AZURE_RBAC_CREDENTIALS }} # set up AZURE_RBAC_CREDENTIALS secrets in your repository + + - name: Setup Node ${{ env.NODE_VERSION }} Environment + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: 'Resolve Project Dependencies Using Npm' + shell: pwsh # For Linux, use bash + run: | + pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}' + npm install + npm run build --if-present + npm run test --if-present + popd + + - name: 'Run Azure Functions Action' + uses: Azure/functions-action@v1 + id: fa + with: + app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }} + package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} + publish-profile: ${{ secrets.AZURE_FUNCTIONAPP_PUBLISH_PROFILE }} # Remove publish-profile to use Azure RBAC From afbcfed2ef4db4eb879b538e4acde5549b72b13c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 22 Jan 2026 05:29:06 +0000 Subject: [PATCH 13/24] feat(client): send `X-Stainless-Kotlin-Version` header --- .../com/pioneer_intergration_app/api/core/ClientOptions.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt index 39a05b8..4b76840 100644 --- a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ClientOptions.kt @@ -398,6 +398,7 @@ private constructor( headers.put("X-Stainless-Package-Version", getPackageVersion()) headers.put("X-Stainless-Runtime", "JRE") headers.put("X-Stainless-Runtime-Version", getJavaVersion()) + headers.put("X-Stainless-Kotlin-Version", KotlinVersion.CURRENT.toString()) apiKey.let { if (!it.isEmpty()) { headers.put("api_key", it) From bf42f71c4925ffb27211a4f9572ed10a980f977d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 07:53:32 +0000 Subject: [PATCH 14/24] fix(tests): add missing query/header params --- .../api/services/ServiceParamsTest.kt | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt index d73658e..80d1c37 100644 --- a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/services/ServiceParamsTest.kt @@ -17,6 +17,7 @@ import com.pioneer_intergration_app.api.client.PioneerIntergrationAppClient import com.pioneer_intergration_app.api.client.okhttp.PioneerIntergrationAppOkHttpClient import com.pioneer_intergration_app.api.models.Order import com.pioneer_intergration_app.api.models.store.StoreListInventoryParams +import com.pioneer_intergration_app.api.models.store.orders.OrderCreateParams import java.time.OffsetDateTime import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled @@ -65,13 +66,19 @@ internal class ServiceParamsTest { stubFor(post(anyUrl()).willReturn(ok("{}"))) orderService.create( - Order.builder() - .id(10L) - .complete(true) - .petId(198772L) - .quantity(7) - .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) - .status(Order.Status.APPROVED) + OrderCreateParams.builder() + .order( + Order.builder() + .id(10L) + .complete(true) + .petId(198772L) + .quantity(7) + .shipDate(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .status(Order.Status.APPROVED) + .build() + ) + .putAdditionalHeader("Secret-Header", "42") + .putAdditionalQueryParam("secret_query_param", "42") .build() ) From eea3a332b8fd86ffd263491c62599e033e0b6d7e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 08:02:46 +0000 Subject: [PATCH 15/24] chore(internal): correct cache invalidation for `SKIP_MOCK_TESTS` --- .../src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts b/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts index 7a74390..1eda9c9 100644 --- a/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/pioneer-intergration-app.kotlin.gradle.kts @@ -33,6 +33,9 @@ kotlin { tasks.withType().configureEach { systemProperty("junit.jupiter.execution.parallel.enabled", true) systemProperty("junit.jupiter.execution.parallel.mode.default", "concurrent") + + // `SKIP_MOCK_TESTS` affects which tests run so it must be added as input for proper cache invalidation. + inputs.property("skipMockTests", System.getenv("SKIP_MOCK_TESTS")).optional(true) } val ktfmt by configurations.creating From 94546f0e320cad92c856cb45fcf205875f495c20 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 23 Jan 2026 08:12:19 +0000 Subject: [PATCH 16/24] fix(client): preserve time zone in lenient date-time parsing --- .../api/core/ObjectMappers.kt | 19 +++++---- .../api/core/ObjectMappersTest.kt | 41 +++++++++++++++---- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt index a924800..c9496b4 100644 --- a/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt +++ b/pioneer-intergration-app-kotlin-core/src/main/kotlin/com/pioneer_intergration_app/api/core/ObjectMappers.kt @@ -25,7 +25,7 @@ import java.time.DateTimeException import java.time.LocalDate import java.time.LocalDateTime import java.time.OffsetDateTime -import java.time.ZonedDateTime +import java.time.ZoneId import java.time.format.DateTimeFormatter import java.time.temporal.ChronoField @@ -157,14 +157,15 @@ private class LenientOffsetDateTimeDeserializer : val temporal = formatter.parse(p.text) return when { - !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> - LocalDate.from(temporal).atStartOfDay() - !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> - LocalDateTime.from(temporal) - else -> ZonedDateTime.from(temporal).toLocalDateTime() - } - .atZone(context.timeZone.toZoneId()) - .toOffsetDateTime() + !temporal.isSupported(ChronoField.HOUR_OF_DAY) -> + LocalDate.from(temporal) + .atStartOfDay() + .atZone(ZoneId.of("UTC")) + .toOffsetDateTime() + !temporal.isSupported(ChronoField.OFFSET_SECONDS) -> + LocalDateTime.from(temporal).atZone(ZoneId.of("UTC")).toOffsetDateTime() + else -> OffsetDateTime.from(temporal) + } } catch (e: DateTimeException) { exceptions.add(e) } diff --git a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt index d841d6a..1648da8 100644 --- a/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt +++ b/pioneer-intergration-app-kotlin-core/src/test/kotlin/com/pioneer_intergration_app/api/core/ObjectMappersTest.kt @@ -3,12 +3,14 @@ package com.pioneer_intergration_app.api.core import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.exc.MismatchedInputException import com.fasterxml.jackson.module.kotlin.readValue +import java.time.LocalDate +import java.time.LocalTime import java.time.OffsetDateTime +import java.time.ZoneOffset import kotlin.reflect.KClass import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.catchThrowable import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.EnumSource import org.junitpioneer.jupiter.cartesian.CartesianTest @@ -72,11 +74,34 @@ internal class ObjectMappersTest { } } - enum class LenientOffsetDateTimeTestCase(val string: String) { - DATE("1998-04-21"), - DATE_TIME("1998-04-21T04:00:00"), - ZONED_DATE_TIME_1("1998-04-21T04:00:00+03:00"), - ZONED_DATE_TIME_2("1998-04-21T04:00:00Z"), + enum class LenientOffsetDateTimeTestCase( + val string: String, + val expectedOffsetDateTime: OffsetDateTime, + ) { + DATE( + "1998-04-21", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(0, 0), ZoneOffset.UTC), + ), + DATE_TIME( + "1998-04-21T04:00:00", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), + ZONED_DATE_TIME_1( + "1998-04-21T04:00:00+03:00", + expectedOffsetDateTime = + OffsetDateTime.of( + LocalDate.of(1998, 4, 21), + LocalTime.of(4, 0), + ZoneOffset.ofHours(3), + ), + ), + ZONED_DATE_TIME_2( + "1998-04-21T04:00:00Z", + expectedOffsetDateTime = + OffsetDateTime.of(LocalDate.of(1998, 4, 21), LocalTime.of(4, 0), ZoneOffset.UTC), + ), } @ParameterizedTest @@ -85,6 +110,8 @@ internal class ObjectMappersTest { val jsonMapper = jsonMapper() val json = jsonMapper.writeValueAsString(testCase.string) - assertDoesNotThrow { jsonMapper().readValue(json) } + val offsetDateTime = jsonMapper().readValue(json) + + assertThat(offsetDateTime).isEqualTo(testCase.expectedOffsetDateTime) } } From 18c47882e214b7cf246a1c22884be84ff0840f81 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:11:14 +0000 Subject: [PATCH 17/24] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 4fbfbe4..f60fd8c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 -config_hash: bbb379c83a14b5543bd8e1734dd2d1c6 +config_hash: fb4996507c52e34ff33a92d9c4c9c63a From b032e3a091fc22440842c69c4e0110e5c7888e82 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:13:15 +0000 Subject: [PATCH 18/24] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index f60fd8c..00e8433 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 -config_hash: fb4996507c52e34ff33a92d9c4c9c63a +config_hash: ec7ca992ab903f2ed190c64c55642cdf From 84a3ed01a1a25cc8b020549202147bf086e189f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:15:12 +0000 Subject: [PATCH 19/24] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 00e8433..d0dc5de 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 -config_hash: ec7ca992ab903f2ed190c64c55642cdf +config_hash: 0d77e3237c93031bc586d10b8b94c39e From bfbb58ca406f1de0c6dcbf49079c99fc240cbc08 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:17:26 +0000 Subject: [PATCH 20/24] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index d0dc5de..94a97d9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 -config_hash: 0d77e3237c93031bc586d10b8b94c39e +config_hash: 4d952be4d78bdf363e00cc8255c0a65b From 752ee4b952add65e7f64e0bdba6db08100a91a49 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 27 Jan 2026 11:19:32 +0000 Subject: [PATCH 21/24] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 94a97d9..a56446c 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 19 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/ummitsmerogersllc%2Fpioneer-intergration-app-21652c2d2e6a5aab678ca435ba09ef698ff34270021f349660b84d5d98bf3923.yml openapi_spec_hash: 356a7298b2abac3fdf72ad5ee046b952 -config_hash: 4d952be4d78bdf363e00cc8255c0a65b +config_hash: 8cc5fee2612d381d6dc5fa26a170b5e6 From 5ad9b393f08b27c6ec87292f7b3bc7ea1c261f94 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 31 Jan 2026 10:07:48 +0000 Subject: [PATCH 22/24] chore(internal): allow passing args to `./scripts/test` --- scripts/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build b/scripts/build index f406348..16a2b00 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 From d0f62ae004a2f302717f688649877cf5bd0a0ed3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 11:57:55 +0000 Subject: [PATCH 23/24] chore(internal): upgrade AssertJ --- pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts | 2 +- pioneer-intergration-app-kotlin-core/build.gradle.kts | 2 +- pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts b/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts index 26042a9..232bf64 100644 --- a/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts +++ b/pioneer-intergration-app-kotlin-client-okhttp/build.gradle.kts @@ -11,5 +11,5 @@ dependencies { implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") testImplementation(kotlin("test")) - testImplementation("org.assertj:assertj-core:3.25.3") + testImplementation("org.assertj:assertj-core:3.27.7") } diff --git a/pioneer-intergration-app-kotlin-core/build.gradle.kts b/pioneer-intergration-app-kotlin-core/build.gradle.kts index a98c04d..34f158e 100644 --- a/pioneer-intergration-app-kotlin-core/build.gradle.kts +++ b/pioneer-intergration-app-kotlin-core/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { testImplementation(kotlin("test")) testImplementation(project(":pioneer-intergration-app-kotlin-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/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts index 2a3069d..ca9b62f 100644 --- a/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts +++ b/pioneer-intergration-app-kotlin-proguard-test/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { testImplementation(project(":pioneer-intergration-app-kotlin")) 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") } From 2cb458d91de0d0c2ef7ae9366b821eca6f647a47 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 7 Feb 2026 11:58:13 +0000 Subject: [PATCH 24/24] release: 0.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 36 +++++++++++++++++++++++++++++++++++ README.md | 10 +++++----- build.gradle.kts | 2 +- 4 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 1332969..3d2ac0b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.1" + ".": "0.1.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0e0ff44 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +## 0.1.0 (2026-02-07) + +Full Changelog: [v0.0.1...v0.1.0](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/compare/v0.0.1...v0.1.0) + +### Features + +* **client:** allow configuring dispatcher executor service ([ee5ba12](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/ee5ba122373a91853a02f648e2d79f3fa5c4ad27)) +* **client:** send `X-Stainless-Kotlin-Version` header ([afbcfed](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/afbcfed2ef4db4eb879b538e4acde5549b72b13c)) + + +### Bug Fixes + +* **client:** disallow coercion from float to int ([a5b0b70](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/a5b0b70ed6c64a7e964b788429d445fb466fd94f)) +* **client:** fully respect max retries ([99fb79e](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/99fb79e69355202787789110d15615b40a927ce6)) +* **client:** preserve time zone in lenient date-time parsing ([94546f0](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/94546f0e320cad92c856cb45fcf205875f495c20)) +* **client:** send retry count header for max retries 0 ([99fb79e](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/99fb79e69355202787789110d15615b40a927ce6)) +* date time deserialization leniency ([e450559](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/e450559d6041ea67c018f05678a12cab3c710253)) +* **tests:** add missing query/header params ([bf42f71](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/bf42f71c4925ffb27211a4f9572ed10a980f977d)) + + +### Chores + +* **ci:** upgrade `actions/setup-java` ([ce82eb8](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/ce82eb8f438a1de87ddba7c944eca968f2b38c9d)) +* **internal:** allow passing args to `./scripts/test` ([5ad9b39](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/5ad9b393f08b27c6ec87292f7b3bc7ea1c261f94)) +* **internal:** codegen related update ([a06486f](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/a06486f32db603002cdc9ef891311a621df0d710)) +* **internal:** codegen related update ([07af80a](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/07af80a3aea53084d0291e9e0d8e09f13b5b27e9)) +* **internal:** correct cache invalidation for `SKIP_MOCK_TESTS` ([eea3a33](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/eea3a332b8fd86ffd263491c62599e033e0b6d7e)) +* **internal:** depend on packages directly in example ([99fb79e](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/99fb79e69355202787789110d15615b40a927ce6)) +* **internal:** refactor build files to support future stainless package uploads ([6024a4f](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/6024a4f7fb7e5b3a48b3067531cc6882bae2c911)) +* **internal:** update `actions/checkout` version ([cd70de1](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/cd70de10007c9dda537b1d71cbf1537954f2e0b2)) +* **internal:** upgrade AssertJ ([d0f62ae](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/d0f62ae004a2f302717f688649877cf5bd0a0ed3)) +* sync repo ([db34c4a](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/db34c4af675d9c7245525201b1da9b6c84a50433)) +* test on Jackson 2.14.0 to avoid encountering FasterXML/jackson-databind[#3240](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/issues/3240) in tests ([e450559](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/e450559d6041ea67c018f05678a12cab3c710253)) +* update SDK settings ([d64728f](https://github.com/ummitsmerogers-droid/GetTrustedInstallerShell/commit/d64728faddd00d52ea2a33faae5453966524c9cb)) diff --git a/README.md b/README.md index d327ecf..a7d4303 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin)](https://central.sonatype.com/artifact/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1) -[![javadoc](https://javadoc.io/badge2/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1/javadoc.svg)](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1) +[![Maven Central](https://img.shields.io/maven-central/v/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin)](https://central.sonatype.com/artifact/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0) +[![javadoc](https://javadoc.io/badge2/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0/javadoc.svg)](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0) @@ -13,7 +13,7 @@ It is generated with [Stainless](https://www.stainless.com/). -KDocs are available on [javadoc.io](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.0.1). +KDocs are available on [javadoc.io](https://javadoc.io/doc/com.pioneer_intergration_app.api/pioneer-intergration-app-kotlin/0.1.0). @@ -24,7 +24,7 @@ KDocs are available on [javadoc.io](https://javadoc.io/doc/com.pioneer_intergrat ### Gradle ```kotlin -implementation("com.pioneer_intergration_app.api:pioneer-intergration-app-kotlin:0.0.1") +implementation("com.pioneer_intergration_app.api:pioneer-intergration-app-kotlin:0.1.0") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.pioneer_intergration_app.api:pioneer-intergration-app-kotlin com.pioneer_intergration_app.api pioneer-intergration-app-kotlin - 0.0.1 + 0.1.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index 90bdf0a..649caa7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ repositories { allprojects { group = "com.pioneer_intergration_app.api" - version = "0.0.1" // x-release-please-version + version = "0.1.0" // x-release-please-version } subprojects {