diff --git a/.github/workflows/publish-sonatype.yml b/.github/workflows/publish-sonatype.yml
index 1247fe9..cabf487 100644
--- a/.github/workflows/publish-sonatype.yml
+++ b/.github/workflows/publish-sonatype.yml
@@ -29,11 +29,13 @@ jobs:
uses: gradle/gradle-build-action@v2
- name: Publish to Sonatype
- run: |
+ 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 publishAndReleaseToMavenCentral --stacktrace -PmavenCentralUsername="$SONATYPE_USERNAME" -PmavenCentralPassword="$SONATYPE_PASSWORD"
env:
SONATYPE_USERNAME: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }}
- GPG_SIGNING_KEY_ID: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_GPG_SIGNING_KEY_ID || secrets.GPG_SIGNING_KEY_ID }}
GPG_SIGNING_KEY: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_GPG_SIGNING_KEY || secrets.GPG_SIGNING_KEY }}
GPG_SIGNING_PASSWORD: ${{ secrets.ONEBUSAWAY_SDK_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
index f328321..fac0542 100644
--- a/.github/workflows/release-doctor.yml
+++ b/.github/workflows/release-doctor.yml
@@ -20,6 +20,5 @@ jobs:
env:
SONATYPE_USERNAME: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_USERNAME || secrets.SONATYPE_USERNAME }}
SONATYPE_PASSWORD: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_PASSWORD || secrets.SONATYPE_PASSWORD }}
- GPG_SIGNING_KEY_ID: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_GPG_SIGNING_KEY_ID || secrets.GPG_SIGNING_KEY_ID }}
GPG_SIGNING_KEY: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_GPG_SIGNING_KEY || secrets.GPG_SIGNING_KEY }}
GPG_SIGNING_PASSWORD: ${{ secrets.ONEBUSAWAY_SDK_SONATYPE_GPG_SIGNING_PASSWORD || secrets.GPG_SIGNING_PASSWORD }}
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 1c0bb88..380b6f9 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.1.0-alpha.23"
+ ".": "0.1.0-alpha.24"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index d4b713b..3928277 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,2 @@
configured_endpoints: 29
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-6f08502508c8ad25235971add3124a1cde4f1c3ec705d5df455d750e0adcb90b.yml
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/open-transit%2Fopen-transit-4fcbe9547537b22a2d68329e1d94e0c1a6f81b5af734ca213f7b95eef5da7adb.yml
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6abeafe..50ee9fb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,25 @@
# Changelog
+## 0.1.0-alpha.24 (2025-05-21)
+
+Full Changelog: [v0.1.0-alpha.23...v0.1.0-alpha.24](https://github.com/OneBusAway/java-sdk/compare/v0.1.0-alpha.23...v0.1.0-alpha.24)
+
+### Features
+
+* **api:** api update ([a9266bd](https://github.com/OneBusAway/java-sdk/commit/a9266bd3053952157431e4aee9b36aae6b637164))
+* **api:** manual updates ([#74](https://github.com/OneBusAway/java-sdk/issues/74)) ([ddda17b](https://github.com/OneBusAway/java-sdk/commit/ddda17b7186ef701720740c946250b5fa902a4cc))
+
+
+### Chores
+
+* **internal:** codegen related update ([#71](https://github.com/OneBusAway/java-sdk/issues/71)) ([c5e90c0](https://github.com/OneBusAway/java-sdk/commit/c5e90c0cda29a9131fd81e60d22711794a2f0a71))
+* **internal:** codegen related update ([#73](https://github.com/OneBusAway/java-sdk/issues/73)) ([a45c6b0](https://github.com/OneBusAway/java-sdk/commit/a45c6b0bc2f45328c1365db12b9ed2fca0d85ce6))
+* **internal:** codegen related update ([#75](https://github.com/OneBusAway/java-sdk/issues/75)) ([a433a99](https://github.com/OneBusAway/java-sdk/commit/a433a99937fdc1729f36a4e7d16a8d90137758e8))
+* **internal:** codegen related update ([#76](https://github.com/OneBusAway/java-sdk/issues/76)) ([a8f595e](https://github.com/OneBusAway/java-sdk/commit/a8f595e2ee1038f8161ab784fd189d074f375d07))
+* **internal:** codegen related update ([#77](https://github.com/OneBusAway/java-sdk/issues/77)) ([14ea7b7](https://github.com/OneBusAway/java-sdk/commit/14ea7b7438268138410dca70f28807ec06f5c5b0))
+* **internal:** codegen related update ([#78](https://github.com/OneBusAway/java-sdk/issues/78)) ([51a4c8c](https://github.com/OneBusAway/java-sdk/commit/51a4c8cab3782706a773525083c4b17da4543064))
+* **internal:** update example values ([#72](https://github.com/OneBusAway/java-sdk/issues/72)) ([9f7aadf](https://github.com/OneBusAway/java-sdk/commit/9f7aadf0b9229f441f1dbfed4b64035f195c3b1e))
+
## 0.1.0-alpha.23 (2024-11-29)
Full Changelog: [v0.1.0-alpha.22...v0.1.0-alpha.23](https://github.com/OneBusAway/java-sdk/compare/v0.1.0-alpha.22...v0.1.0-alpha.23)
diff --git a/LICENSE b/LICENSE
index 9e6f6ec..443d70c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.
- Copyright 2024 Onebusaway SDK
+ Copyright 2025 Onebusaway SDK
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/README.md b/README.md
index 7dd1dc3..f771e77 100644
--- a/README.md
+++ b/README.md
@@ -2,46 +2,46 @@
-[](https://central.sonatype.com/artifact/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.23)
+[](https://central.sonatype.com/artifact/org.onebusaway/onebusaway-sdk-java/0.1.0-alpha.24)
-The Onebusaway SDK Java SDK provides convenient access to the Onebusaway SDK REST API from applications written in Java. It includes helper classes with helpful types and documentation for every request and response property.
+The Onebusaway SDK Java SDK provides convenient access to the Onebusaway SDK REST API from applications written in Java.
The Onebusaway SDK Java SDK is similar to the Onebusaway SDK Kotlin SDK but with minor differences that make it more ergonomic for use in Java, such as `Optional` instead of nullable values, `Stream` instead of `Sequence`, and `CompletableFuture` instead of suspend functions.
It is generated with [Stainless](https://www.stainlessapi.com/).
-## Documentation
+The REST API documentation can be found on [developer.onebusaway.org](https://developer.onebusaway.org).
-The REST API documentation can be found on [developer.onebusaway.org](https://developer.onebusaway.org).
-
----
-
-## Getting started
-
-### Install dependencies
-
-#### Gradle
+## Installation
+### Gradle
+
```kotlin
-implementation("org.onebusaway:onebusaway-sdk-java:0.1.0-alpha.23")
+implementation("org.onebusaway:onebusaway-sdk-java:0.1.0-alpha.24")
```
-#### Maven
+### Maven
```xml
org.onebusaway
onebusaway-sdk-java
- 0.1.0-alpha.23
+ 0.1.0-alpha.24
```
+## Requirements
+
+This library requires Java 8 or later.
+
+## Usage
+
### Configure the client
Use `OnebusawaySdkOkHttpClient.builder()` to configure the client. At a minimum you need to set `.apiKey()`:
@@ -58,6 +58,9 @@ OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
Alternately, set the environment with `ONEBUSAWAY_API_KEY`, and use `OnebusawaySdkOkHttpClient.fromEnv()` to read from the environment.
```java
+import org.onebusaway.client.OnebusawaySdkClient;
+import org.onebusaway.client.okhttp.OnebusawaySdkOkHttpClient;
+
OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.fromEnv();
// Note: you can also call fromEnv() from the client builder, for example if you need to set additional properties
@@ -77,8 +80,7 @@ Read the documentation for more configuration options.
### Example: creating a resource
-To create a new current time, first use the `CurrentTimeRetrieveParams` builder to specify attributes,
-then pass that to the `retrieve` method of the `currentTime` service.
+To create a new current time, first use the `CurrentTimeRetrieveParams` builder to specify attributes, then pass that to the `retrieve` method of the `currentTime` service.
```java
import org.onebusaway.models.CurrentTimeRetrieveParams;
@@ -96,19 +98,7 @@ CurrentTimeRetrieveResponse currentTime = client.currentTime().retrieve(params);
To make a request to the Onebusaway SDK API, you generally build an instance of the appropriate `Params` class.
-In [Example: creating a resource](#example-creating-a-resource) above, we used the `CurrentTimeRetrieveParams.builder()` to pass to
-the `retrieve` method of the `currentTime` service.
-
-Sometimes, the API may support other properties that are not yet supported in the Java SDK types. In that case,
-you can attach them using the `putAdditionalProperty` method.
-
-```java
-import org.onebusaway.models.core.JsonValue;
-CurrentTimeRetrieveParams params = CurrentTimeRetrieveParams.builder()
- // ... normal properties
- .putAdditionalProperty("secret_param", JsonValue.from("4242"))
- .build();
-```
+See [Undocumented request params](#undocumented-request-params) for how to send arbitrary parameters.
## Responses
@@ -117,15 +107,19 @@ CurrentTimeRetrieveParams params = CurrentTimeRetrieveParams.builder()
When receiving a response, the Onebusaway SDK Java SDK will deserialize it into instances of the typed model classes. In rare cases, the API may return a response property that doesn't match the expected Java type. If you directly access the mistaken property, the SDK will throw an unchecked `OnebusawaySdkInvalidDataException` at runtime. If you would prefer to check in advance that that response is completely well-typed, call `.validate()` on the returned model.
```java
+import org.onebusaway.models.CurrentTimeRetrieveResponse;
+
CurrentTimeRetrieveResponse currentTime = client.currentTime().retrieve().validate();
```
### Response properties as JSON
-In rare cases, you may want to access the underlying JSON value for a response property rather than using the typed version provided by
-this SDK. Each model property has a corresponding JSON version, with an underscore before the method name, which returns a `JsonField` value.
+In rare cases, you may want to access the underlying JSON value for a response property rather than using the typed version provided by this SDK. Each model property has a corresponding JSON version, with an underscore before the method name, which returns a `JsonField` value.
```java
+import java.util.Optional;
+import org.onebusaway.core.JsonField;
+
JsonField field = responseObj._field();
if (field.isMissing()) {
@@ -147,6 +141,8 @@ if (field.isMissing()) {
Sometimes, the server response may include additional properties that are not yet available in this library's types. You can access them using the model's `_additionalProperties` method:
```java
+import org.onebusaway.core.JsonValue;
+
JsonValue secret = references._additionalProperties().get("secret_field");
```
@@ -160,31 +156,33 @@ This library throws exceptions in a single hierarchy for easy handling:
- **`OnebusawaySdkException`** - Base exception for all exceptions
- - **`OnebusawaySdkServiceException`** - HTTP errors with a well-formed response body we were able to parse. The exception message and the `.debuggingRequestId()` will be set by the server.
+- **`OnebusawaySdkServiceException`** - HTTP errors with a well-formed response body we were able to parse. The exception message and the `.debuggingRequestId()` will be set by the server.
- | 400 | BadRequestException |
- | ------ | ----------------------------- |
- | 401 | AuthenticationException |
- | 403 | PermissionDeniedException |
- | 404 | NotFoundException |
- | 422 | UnprocessableEntityException |
- | 429 | RateLimitException |
- | 5xx | InternalServerException |
- | others | UnexpectedStatusCodeException |
+ | 400 | BadRequestException |
+ | ------ | ----------------------------- |
+ | 401 | AuthenticationException |
+ | 403 | PermissionDeniedException |
+ | 404 | NotFoundException |
+ | 422 | UnprocessableEntityException |
+ | 429 | RateLimitException |
+ | 5xx | InternalServerException |
+ | others | UnexpectedStatusCodeException |
- - **`OnebusawaySdkIoException`** - I/O networking errors
- - **`OnebusawaySdkInvalidDataException`** - any other exceptions on the client side, e.g.:
- - We failed to serialize the request body
- - We failed to parse the response body (has access to response code and body)
+- **`OnebusawaySdkIoException`** - I/O networking errors
+- **`OnebusawaySdkInvalidDataException`** - any other exceptions on the client side, e.g.:
+ - We failed to serialize the request body
+ - We failed to parse the response body (has access to response code and body)
## Network options
### Retries
-Requests that experience certain errors are automatically retried 2 times by default, with a short exponential backoff. Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors will all be retried by default.
-You can provide a `maxRetries` on the client builder to configure this:
+Requests that experience certain errors are automatically retried 2 times by default, with a short exponential backoff. Connection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors will all be retried by default. You can provide a `maxRetries` on the client builder to configure this:
```java
+import org.onebusaway.client.OnebusawaySdkClient;
+import org.onebusaway.client.okhttp.OnebusawaySdkOkHttpClient;
+
OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
.fromEnv()
.maxRetries(4)
@@ -196,6 +194,10 @@ OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
Requests time out after 1 minute by default. You can configure this on the client builder:
```java
+import java.time.Duration;
+import org.onebusaway.client.OnebusawaySdkClient;
+import org.onebusaway.client.okhttp.OnebusawaySdkOkHttpClient;
+
OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
.fromEnv()
.timeout(Duration.ofSeconds(30))
@@ -207,50 +209,67 @@ OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
Requests can be routed through a proxy. You can configure this on the client builder:
```java
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import org.onebusaway.client.OnebusawaySdkClient;
+import org.onebusaway.client.okhttp.OnebusawaySdkOkHttpClient;
+
OnebusawaySdkClient client = OnebusawaySdkOkHttpClient.builder()
.fromEnv()
- .proxy(new Proxy(
- Type.HTTP,
- new InetSocketAddress("proxy.com", 8080)
- ))
+ .proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("example.com", 8080)))
.build();
```
## Making custom/undocumented requests
-This library is typed for convenient access to the documented API. If you need to access undocumented
-params or response properties, the library can still be used.
+This library is typed for convenient access to the documented API. If you need to access undocumented params or response properties, the library can still be used.
### Undocumented request params
-To make requests using undocumented parameters, you can provide or override parameters on the params object
-while building it.
+In [Example: creating a resource](#example-creating-a-resource) above, we used the `CurrentTimeRetrieveParams.builder()` to pass to the `retrieve` method of the `currentTime` service.
-```kotlin
-FooCreateParams address = FooCreateParams.builder()
- .id("my_id")
- .putAdditionalProperty("secret_prop", JsonValue.from("hello"))
+Sometimes, the API may support other properties that are not yet supported in the Java SDK types. In that case, you can attach them using raw setters:
+
+```java
+import org.onebusaway.core.JsonValue;
+import org.onebusaway.models.CurrentTimeRetrieveParams;
+
+CurrentTimeRetrieveParams params = CurrentTimeRetrieveParams.builder()
+ .putAdditionalHeader("Secret-Header", "42")
+ .putAdditionalQueryParam("secret_query_param", "42")
+ .putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))
.build();
```
+You can also use the `putAdditionalProperty` method on nested headers, query params, or body objects.
+
### Undocumented response properties
-To access undocumented response properties, you can use `res._additionalProperties()` on a response object to
-get a map of untyped fields of type `Map`. You can then access fields like
-`._additionalProperties().get("secret_prop").asString()` or use other helpers defined on the `JsonValue` class
-to extract it to a desired type.
+To access undocumented response properties, you can use `res._additionalProperties()` on a response object to get a map of untyped fields of type `Map`. You can then access fields like `res._additionalProperties().get("secret_prop").asString()` or use other helpers defined on the `JsonValue` class to extract it to a desired type.
+
+## Logging
+
+We use the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).
+
+You can enable logging by setting the environment variable `ONEBUSAWAY_SDK_LOG` to `info`.
+
+```sh
+$ export ONEBUSAWAY_SDK_LOG=info
+```
+
+Or to `debug` for more verbose logging.
+
+```sh
+$ export ONEBUSAWAY_SDK_LOG=debug
+```
## 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)_.
+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/OneBusAway/java-sdk/issues) with questions, bugs, or suggestions.
-
-## Requirements
-
-This library requires Java 8 or later.
diff --git a/build.gradle.kts b/build.gradle.kts
index 8c8ea48..cc7e656 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,10 +1,4 @@
-plugins {
-
-}
-
allprojects {
group = "org.onebusaway"
- version = "0.1.0-alpha.23" // x-release-please-version
+ version = "0.1.0-alpha.24" // x-release-please-version
}
-
-
diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts
index 493cb32..8a1d7a1 100644
--- a/buildSrc/build.gradle.kts
+++ b/buildSrc/build.gradle.kts
@@ -1,6 +1,6 @@
plugins {
`kotlin-dsl`
- kotlin("jvm") version "1.9.22"
+ kotlin("jvm") version "2.1.0"
id("com.vanniktech.maven.publish") version "0.28.0"
}
diff --git a/buildSrc/src/main/kotlin/onebusaway-sdk.java.gradle.kts b/buildSrc/src/main/kotlin/onebusaway-sdk.java.gradle.kts
index 32a150e..a2c35b9 100644
--- a/buildSrc/src/main/kotlin/onebusaway-sdk.java.gradle.kts
+++ b/buildSrc/src/main/kotlin/onebusaway-sdk.java.gradle.kts
@@ -1,9 +1,5 @@
import com.diffplug.gradle.spotless.SpotlessExtension
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
-import com.vanniktech.maven.publish.JavaLibrary
-import com.vanniktech.maven.publish.JavadocJar
-import com.vanniktech.maven.publish.MavenPublishBaseExtension
-import com.vanniktech.maven.publish.SonatypeHost
plugins {
`java-library`
diff --git a/buildSrc/src/main/kotlin/onebusaway-sdk.kotlin.gradle.kts b/buildSrc/src/main/kotlin/onebusaway-sdk.kotlin.gradle.kts
index 6da1ac7..5eecc1c 100644
--- a/buildSrc/src/main/kotlin/onebusaway-sdk.kotlin.gradle.kts
+++ b/buildSrc/src/main/kotlin/onebusaway-sdk.kotlin.gradle.kts
@@ -1,6 +1,5 @@
import com.diffplug.gradle.spotless.SpotlessExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
-import com.vanniktech.maven.publish.*
plugins {
id("onebusaway-sdk.java")
@@ -22,8 +21,12 @@ configure {
tasks.withType().configureEach {
kotlinOptions {
- allWarningsAsErrors = true
- freeCompilerArgs = listOf("-Xjvm-default=all", "-Xjdk-release=1.8")
+ freeCompilerArgs = listOf(
+ "-Xjvm-default=all",
+ "-Xjdk-release=1.8",
+ // Suppress deprecation warnings because we may still reference and test deprecated members.
+ "-Xsuppress-warning=DEPRECATION"
+ )
jvmTarget = "1.8"
}
}
diff --git a/buildSrc/src/main/kotlin/onebusaway-sdk.publish.gradle.kts b/buildSrc/src/main/kotlin/onebusaway-sdk.publish.gradle.kts
index 4c6d7fa..457c5c2 100644
--- a/buildSrc/src/main/kotlin/onebusaway-sdk.publish.gradle.kts
+++ b/buildSrc/src/main/kotlin/onebusaway-sdk.publish.gradle.kts
@@ -1,10 +1,3 @@
-import org.gradle.api.publish.PublishingExtension
-import org.gradle.api.publish.maven.MavenPublication
-import org.gradle.kotlin.dsl.configure
-import org.gradle.kotlin.dsl.register
-import org.gradle.kotlin.dsl.get
-import com.vanniktech.maven.publish.JavaLibrary
-import com.vanniktech.maven.publish.JavadocJar
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import com.vanniktech.maven.publish.SonatypeHost
@@ -25,7 +18,7 @@ configure {
signAllPublications()
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
- this.coordinates(project.group.toString(), project.name, project.version.toString())
+ coordinates(project.group.toString(), project.name, project.version.toString())
pom {
name.set("OneBusAway")
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index e644113..a4b76b9 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index b82aa23..cea7a79 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
index 1aa94a4..f3b75f3 100755
--- a/gradlew
+++ b/gradlew
@@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+# SPDX-License-Identifier: Apache-2.0
+#
##############################################################################
#
@@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# 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/.
@@ -84,7 +86,7 @@ done
# 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 "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+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
diff --git a/gradlew.bat b/gradlew.bat
index 25da30d..9d21a21 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,6 +13,8 @@
@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 ##########################################################################
diff --git a/onebusaway-sdk-java-client-okhttp/build.gradle.kts b/onebusaway-sdk-java-client-okhttp/build.gradle.kts
index 037ef81..2fd0abf 100644
--- a/onebusaway-sdk-java-client-okhttp/build.gradle.kts
+++ b/onebusaway-sdk-java-client-okhttp/build.gradle.kts
@@ -6,10 +6,9 @@ plugins {
dependencies {
api(project(":onebusaway-sdk-java-core"))
- implementation("com.google.guava:guava:33.0.0-jre")
implementation("com.squareup.okhttp3:okhttp:4.12.0")
+ implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
testImplementation(kotlin("test"))
testImplementation("org.assertj:assertj-core:3.25.3")
- testImplementation("org.slf4j:slf4j-simple:2.0.12")
}
diff --git a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt
index 427df17..16d85ce 100644
--- a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt
+++ b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OkHttpClient.kt
@@ -1,7 +1,5 @@
package org.onebusaway.client.okhttp
-import com.google.common.collect.ListMultimap
-import com.google.common.collect.MultimapBuilder
import java.io.IOException
import java.io.InputStream
import java.net.Proxy
@@ -9,17 +7,20 @@ import java.time.Duration
import java.util.concurrent.CompletableFuture
import okhttp3.Call
import okhttp3.Callback
-import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
+import okhttp3.Interceptor
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
import org.onebusaway.core.RequestOptions
+import org.onebusaway.core.checkRequired
+import org.onebusaway.core.http.Headers
import org.onebusaway.core.http.HttpClient
import org.onebusaway.core.http.HttpMethod
import org.onebusaway.core.http.HttpRequest
@@ -31,22 +32,11 @@ class OkHttpClient
private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val baseUrl: HttpUrl) :
HttpClient {
- private fun getClient(requestOptions: RequestOptions): okhttp3.OkHttpClient {
- val timeout = requestOptions.timeout ?: return okHttpClient
- return okHttpClient
- .newBuilder()
- .connectTimeout(timeout)
- .readTimeout(timeout)
- .writeTimeout(timeout)
- .callTimeout(if (timeout.seconds == 0L) timeout else timeout.plusSeconds(30))
- .build()
- }
-
override fun execute(
request: HttpRequest,
requestOptions: RequestOptions,
): HttpResponse {
- val call = getClient(requestOptions).newCall(request.toRequest())
+ val call = newCall(request, requestOptions)
return try {
call.execute().toResponse()
@@ -65,18 +55,18 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
request.body?.run { future.whenComplete { _, _ -> close() } }
- val call = getClient(requestOptions).newCall(request.toRequest())
- call.enqueue(
- object : Callback {
- override fun onResponse(call: Call, response: Response) {
- future.complete(response.toResponse())
- }
+ newCall(request, requestOptions)
+ .enqueue(
+ object : Callback {
+ override fun onResponse(call: Call, response: Response) {
+ future.complete(response.toResponse())
+ }
- override fun onFailure(call: Call, e: IOException) {
- future.completeExceptionally(OnebusawaySdkIoException("Request failed", e))
+ override fun onFailure(call: Call, e: IOException) {
+ future.completeExceptionally(OnebusawaySdkIoException("Request failed", e))
+ }
}
- }
- )
+ )
return future
}
@@ -87,19 +77,73 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
okHttpClient.cache?.close()
}
- private fun HttpRequest.toRequest(): Request {
+ private fun newCall(request: HttpRequest, requestOptions: RequestOptions): Call {
+ val clientBuilder = okHttpClient.newBuilder()
+
+ // Custom logging interceptor for URL logging
+ clientBuilder.addNetworkInterceptor(LoggingInterceptor())
+
+ val logLevel =
+ when (System.getenv("ONEBUSAWAY_SDK_LOG")?.lowercase()) {
+ "info" -> HttpLoggingInterceptor.Level.BASIC
+ "debug" -> HttpLoggingInterceptor.Level.BODY
+ else -> null
+ }
+ if (logLevel != null) {
+ clientBuilder.addNetworkInterceptor(HttpLoggingInterceptor().setLevel(logLevel))
+ }
+
+ val timeout = requestOptions.timeout
+ if (timeout != null) {
+ clientBuilder
+ .connectTimeout(timeout)
+ .readTimeout(timeout)
+ .writeTimeout(timeout)
+ .callTimeout(if (timeout.seconds == 0L) timeout else timeout.plusSeconds(30))
+ }
+
+ val client = clientBuilder.build()
+ return client.newCall(request.toRequest(client))
+ }
+
+ private fun HttpRequest.toRequest(client: okhttp3.OkHttpClient): Request {
var body: RequestBody? = body?.toRequestBody()
- // OkHttpClient always requires a request body for PUT and POST methods.
- if (body == null && (method == HttpMethod.PUT || method == HttpMethod.POST)) {
+ if (body == null && requiresBody(method)) {
body = "".toRequestBody()
}
val builder = Request.Builder().url(toUrl()).method(method.name, body)
- headers.forEach(builder::header)
+ headers.names().forEach { name ->
+ headers.values(name).forEach { builder.header(name, it) }
+ }
+
+ if (
+ !headers.names().contains("X-Stainless-Read-Timeout") && client.readTimeoutMillis != 0
+ ) {
+ builder.header(
+ "X-Stainless-Read-Timeout",
+ Duration.ofMillis(client.readTimeoutMillis.toLong()).seconds.toString()
+ )
+ }
+ if (!headers.names().contains("X-Stainless-Timeout") && client.callTimeoutMillis != 0) {
+ builder.header(
+ "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 {
url?.let {
return it
@@ -107,7 +151,9 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
val builder = baseUrl.newBuilder()
pathSegments.forEach(builder::addPathSegment)
- queryParams.forEach(builder::addQueryParameter)
+ queryParams.keys().forEach { key ->
+ queryParams.values(key).forEach { builder.addQueryParameter(key, it) }
+ }
return builder.toString()
}
@@ -133,7 +179,7 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
return object : HttpResponse {
override fun statusCode(): Int = code
- override fun headers(): ListMultimap = headers
+ override fun headers(): Headers = headers
override fun body(): InputStream = body!!.byteStream()
@@ -141,20 +187,17 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
}
}
- private fun Headers.toHeaders(): ListMultimap {
- val headers =
- MultimapBuilder.treeKeys(String.CASE_INSENSITIVE_ORDER)
- .arrayListValues()
- .build()
- forEach { pair -> headers.put(pair.first, pair.second) }
- return headers
+ private fun okhttp3.Headers.toHeaders(): Headers {
+ val headersBuilder = Headers.builder()
+ forEach { (name, value) -> headersBuilder.put(name, value) }
+ return headersBuilder.build()
}
companion object {
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ class Builder internal constructor() {
private var baseUrl: HttpUrl? = null
// The default timeout is 1 minute.
@@ -176,7 +219,18 @@ private constructor(private val okHttpClient: okhttp3.OkHttpClient, private val
.callTimeout(if (timeout.seconds == 0L) timeout else timeout.plusSeconds(30))
.proxy(proxy)
.build(),
- checkNotNull(baseUrl) { "`baseUrl` is required but was not set" },
+ checkRequired("baseUrl", baseUrl),
)
}
}
+
+// --- ✅ New class added below ---
+class LoggingInterceptor : Interceptor {
+ override fun intercept(chain: Interceptor.Chain): Response {
+ val request = chain.request()
+ println("➡️ Sending request: ${request.method} ${request.url}")
+ val response = chain.proceed(request)
+ println("⬅️ Received response: ${response.code} ${response.request.url}")
+ return response
+ }
+}
diff --git a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt
index 4c71daa..807aa13 100644
--- a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt
+++ b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClient.kt
@@ -9,6 +9,8 @@ import java.time.Duration
import org.onebusaway.client.OnebusawaySdkClient
import org.onebusaway.client.OnebusawaySdkClientImpl
import org.onebusaway.core.ClientOptions
+import org.onebusaway.core.http.Headers
+import org.onebusaway.core.http.QueryParams
class OnebusawaySdkOkHttpClient private constructor() {
@@ -19,7 +21,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
@JvmStatic fun fromEnv(): OnebusawaySdkClient = builder().fromEnv().build()
}
- class Builder {
+ /** A builder for [OnebusawaySdkOkHttpClient]. */
+ class Builder internal constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var baseUrl: String = ClientOptions.PRODUCTION_URL
@@ -36,6 +39,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
fun clock(clock: Clock) = apply { clientOptions.clock(clock) }
+ fun headers(headers: Headers) = apply { clientOptions.headers(headers) }
+
fun headers(headers: Map>) = apply {
clientOptions.headers(headers)
}
@@ -46,6 +51,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
clientOptions.putHeaders(name, values)
}
+ fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) }
+
fun putAllHeaders(headers: Map>) = apply {
clientOptions.putAllHeaders(headers)
}
@@ -58,6 +65,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
clientOptions.replaceHeaders(name, values)
}
+ fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) }
+
fun replaceAllHeaders(headers: Map>) = apply {
clientOptions.replaceAllHeaders(headers)
}
@@ -66,6 +75,8 @@ class OnebusawaySdkOkHttpClient private constructor() {
fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) }
+ fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) }
+
fun queryParams(queryParams: Map>) = apply {
clientOptions.queryParams(queryParams)
}
@@ -78,6 +89,10 @@ class OnebusawaySdkOkHttpClient private constructor() {
clientOptions.putQueryParams(key, values)
}
+ fun putAllQueryParams(queryParams: QueryParams) = apply {
+ clientOptions.putAllQueryParams(queryParams)
+ }
+
fun putAllQueryParams(queryParams: Map>) = apply {
clientOptions.putAllQueryParams(queryParams)
}
@@ -90,6 +105,10 @@ class OnebusawaySdkOkHttpClient private constructor() {
clientOptions.replaceQueryParams(key, values)
}
+ fun replaceAllQueryParams(queryParams: QueryParams) = apply {
+ clientOptions.replaceAllQueryParams(queryParams)
+ }
+
fun replaceAllQueryParams(queryParams: Map>) = apply {
clientOptions.replaceAllQueryParams(queryParams)
}
diff --git a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt
index 00ea3d2..6611264 100644
--- a/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt
+++ b/onebusaway-sdk-java-client-okhttp/src/main/kotlin/org/onebusaway/client/okhttp/OnebusawaySdkOkHttpClientAsync.kt
@@ -9,6 +9,8 @@ import java.time.Duration
import org.onebusaway.client.OnebusawaySdkClientAsync
import org.onebusaway.client.OnebusawaySdkClientAsyncImpl
import org.onebusaway.core.ClientOptions
+import org.onebusaway.core.http.Headers
+import org.onebusaway.core.http.QueryParams
class OnebusawaySdkOkHttpClientAsync private constructor() {
@@ -19,7 +21,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
@JvmStatic fun fromEnv(): OnebusawaySdkClientAsync = builder().fromEnv().build()
}
- class Builder {
+ /** A builder for [OnebusawaySdkOkHttpClientAsync]. */
+ class Builder internal constructor() {
private var clientOptions: ClientOptions.Builder = ClientOptions.builder()
private var baseUrl: String = ClientOptions.PRODUCTION_URL
@@ -36,6 +39,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
fun clock(clock: Clock) = apply { clientOptions.clock(clock) }
+ fun headers(headers: Headers) = apply { clientOptions.headers(headers) }
+
fun headers(headers: Map>) = apply {
clientOptions.headers(headers)
}
@@ -46,6 +51,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
clientOptions.putHeaders(name, values)
}
+ fun putAllHeaders(headers: Headers) = apply { clientOptions.putAllHeaders(headers) }
+
fun putAllHeaders(headers: Map>) = apply {
clientOptions.putAllHeaders(headers)
}
@@ -58,6 +65,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
clientOptions.replaceHeaders(name, values)
}
+ fun replaceAllHeaders(headers: Headers) = apply { clientOptions.replaceAllHeaders(headers) }
+
fun replaceAllHeaders(headers: Map>) = apply {
clientOptions.replaceAllHeaders(headers)
}
@@ -66,6 +75,8 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
fun removeAllHeaders(names: Set) = apply { clientOptions.removeAllHeaders(names) }
+ fun queryParams(queryParams: QueryParams) = apply { clientOptions.queryParams(queryParams) }
+
fun queryParams(queryParams: Map>) = apply {
clientOptions.queryParams(queryParams)
}
@@ -78,6 +89,10 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
clientOptions.putQueryParams(key, values)
}
+ fun putAllQueryParams(queryParams: QueryParams) = apply {
+ clientOptions.putAllQueryParams(queryParams)
+ }
+
fun putAllQueryParams(queryParams: Map>) = apply {
clientOptions.putAllQueryParams(queryParams)
}
@@ -90,6 +105,10 @@ class OnebusawaySdkOkHttpClientAsync private constructor() {
clientOptions.replaceQueryParams(key, values)
}
+ fun replaceAllQueryParams(queryParams: QueryParams) = apply {
+ clientOptions.replaceAllQueryParams(queryParams)
+ }
+
fun replaceAllQueryParams(queryParams: Map>) = apply {
clientOptions.replaceAllQueryParams(queryParams)
}
diff --git a/onebusaway-sdk-java-core/build.gradle.kts b/onebusaway-sdk-java-core/build.gradle.kts
index 8f52193..6a0859b 100644
--- a/onebusaway-sdk-java-core/build.gradle.kts
+++ b/onebusaway-sdk-java-core/build.gradle.kts
@@ -4,14 +4,13 @@ plugins {
}
dependencies {
- api("com.fasterxml.jackson.core:jackson-core:2.14.3")
- api("com.fasterxml.jackson.core:jackson-databind:2.14.3")
- api("com.google.guava:guava:33.0.0-jre")
+ api("com.fasterxml.jackson.core:jackson-core:2.18.1")
+ api("com.fasterxml.jackson.core:jackson-databind:2.18.1")
- implementation("com.fasterxml.jackson.core:jackson-annotations:2.14.3")
- implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.14.3")
- implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.14.3")
- implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.3")
+ implementation("com.fasterxml.jackson.core:jackson-annotations:2.18.1")
+ implementation("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.18.1")
+ implementation("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.18.1")
+ implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.1")
implementation("org.apache.httpcomponents.core5:httpcore5:5.2.4")
implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1")
@@ -19,8 +18,9 @@ dependencies {
testImplementation(project(":onebusaway-sdk-java-client-okhttp"))
testImplementation("com.github.tomakehurst:wiremock-jre8:2.35.2")
testImplementation("org.assertj:assertj-core:3.25.3")
- testImplementation("org.assertj:assertj-guava:3.25.3")
- testImplementation("org.slf4j:slf4j-simple:2.0.12")
testImplementation("org.junit.jupiter:junit-jupiter-api:5.9.3")
testImplementation("org.junit.jupiter:junit-jupiter-params:5.9.3")
+ 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/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClient.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClient.kt
index 44afaea..b09d68b 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClient.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClient.kt
@@ -2,11 +2,57 @@
package org.onebusaway.client
-import org.onebusaway.models.*
-import org.onebusaway.services.blocking.*
-
+import org.onebusaway.services.blocking.AgenciesWithCoverageService
+import org.onebusaway.services.blocking.AgencyService
+import org.onebusaway.services.blocking.ArrivalAndDepartureService
+import org.onebusaway.services.blocking.BlockService
+import org.onebusaway.services.blocking.ConfigService
+import org.onebusaway.services.blocking.CurrentTimeService
+import org.onebusaway.services.blocking.ReportProblemWithStopService
+import org.onebusaway.services.blocking.ReportProblemWithTripService
+import org.onebusaway.services.blocking.RouteIdsForAgencyService
+import org.onebusaway.services.blocking.RouteService
+import org.onebusaway.services.blocking.RoutesForAgencyService
+import org.onebusaway.services.blocking.RoutesForLocationService
+import org.onebusaway.services.blocking.ScheduleForRouteService
+import org.onebusaway.services.blocking.ScheduleForStopService
+import org.onebusaway.services.blocking.SearchForRouteService
+import org.onebusaway.services.blocking.SearchForStopService
+import org.onebusaway.services.blocking.ShapeService
+import org.onebusaway.services.blocking.StopIdsForAgencyService
+import org.onebusaway.services.blocking.StopService
+import org.onebusaway.services.blocking.StopsForAgencyService
+import org.onebusaway.services.blocking.StopsForLocationService
+import org.onebusaway.services.blocking.StopsForRouteService
+import org.onebusaway.services.blocking.TripDetailService
+import org.onebusaway.services.blocking.TripForVehicleService
+import org.onebusaway.services.blocking.TripService
+import org.onebusaway.services.blocking.TripsForLocationService
+import org.onebusaway.services.blocking.TripsForRouteService
+import org.onebusaway.services.blocking.VehiclesForAgencyService
+
+/**
+ * A client for interacting with the Onebusaway SDK 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 OnebusawaySdkClient {
+ /**
+ * 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(): OnebusawaySdkClientAsync
fun agenciesWithCoverage(): AgenciesWithCoverageService
@@ -64,4 +110,17 @@ interface OnebusawaySdkClient {
fun block(): BlockService
fun shape(): ShapeService
+
+ /**
+ * 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()
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsync.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsync.kt
index 0029e0f..aee0c2e 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsync.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsync.kt
@@ -2,11 +2,57 @@
package org.onebusaway.client
-import org.onebusaway.models.*
-import org.onebusaway.services.async.*
-
+import org.onebusaway.services.async.AgenciesWithCoverageServiceAsync
+import org.onebusaway.services.async.AgencyServiceAsync
+import org.onebusaway.services.async.ArrivalAndDepartureServiceAsync
+import org.onebusaway.services.async.BlockServiceAsync
+import org.onebusaway.services.async.ConfigServiceAsync
+import org.onebusaway.services.async.CurrentTimeServiceAsync
+import org.onebusaway.services.async.ReportProblemWithStopServiceAsync
+import org.onebusaway.services.async.ReportProblemWithTripServiceAsync
+import org.onebusaway.services.async.RouteIdsForAgencyServiceAsync
+import org.onebusaway.services.async.RouteServiceAsync
+import org.onebusaway.services.async.RoutesForAgencyServiceAsync
+import org.onebusaway.services.async.RoutesForLocationServiceAsync
+import org.onebusaway.services.async.ScheduleForRouteServiceAsync
+import org.onebusaway.services.async.ScheduleForStopServiceAsync
+import org.onebusaway.services.async.SearchForRouteServiceAsync
+import org.onebusaway.services.async.SearchForStopServiceAsync
+import org.onebusaway.services.async.ShapeServiceAsync
+import org.onebusaway.services.async.StopIdsForAgencyServiceAsync
+import org.onebusaway.services.async.StopServiceAsync
+import org.onebusaway.services.async.StopsForAgencyServiceAsync
+import org.onebusaway.services.async.StopsForLocationServiceAsync
+import org.onebusaway.services.async.StopsForRouteServiceAsync
+import org.onebusaway.services.async.TripDetailServiceAsync
+import org.onebusaway.services.async.TripForVehicleServiceAsync
+import org.onebusaway.services.async.TripServiceAsync
+import org.onebusaway.services.async.TripsForLocationServiceAsync
+import org.onebusaway.services.async.TripsForRouteServiceAsync
+import org.onebusaway.services.async.VehiclesForAgencyServiceAsync
+
+/**
+ * A client for interacting with the Onebusaway SDK 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 OnebusawaySdkClientAsync {
+ /**
+ * 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(): OnebusawaySdkClient
fun agenciesWithCoverage(): AgenciesWithCoverageServiceAsync
@@ -64,4 +110,17 @@ interface OnebusawaySdkClientAsync {
fun block(): BlockServiceAsync
fun shape(): ShapeServiceAsync
+
+ /**
+ * 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()
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsyncImpl.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsyncImpl.kt
index f930dc9..5c218c1 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsyncImpl.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientAsyncImpl.kt
@@ -4,16 +4,69 @@ package org.onebusaway.client
import org.onebusaway.core.ClientOptions
import org.onebusaway.core.getPackageVersion
-import org.onebusaway.models.*
-import org.onebusaway.services.async.*
-
-class OnebusawaySdkClientAsyncImpl
-constructor(
+import org.onebusaway.services.async.AgenciesWithCoverageServiceAsync
+import org.onebusaway.services.async.AgenciesWithCoverageServiceAsyncImpl
+import org.onebusaway.services.async.AgencyServiceAsync
+import org.onebusaway.services.async.AgencyServiceAsyncImpl
+import org.onebusaway.services.async.ArrivalAndDepartureServiceAsync
+import org.onebusaway.services.async.ArrivalAndDepartureServiceAsyncImpl
+import org.onebusaway.services.async.BlockServiceAsync
+import org.onebusaway.services.async.BlockServiceAsyncImpl
+import org.onebusaway.services.async.ConfigServiceAsync
+import org.onebusaway.services.async.ConfigServiceAsyncImpl
+import org.onebusaway.services.async.CurrentTimeServiceAsync
+import org.onebusaway.services.async.CurrentTimeServiceAsyncImpl
+import org.onebusaway.services.async.ReportProblemWithStopServiceAsync
+import org.onebusaway.services.async.ReportProblemWithStopServiceAsyncImpl
+import org.onebusaway.services.async.ReportProblemWithTripServiceAsync
+import org.onebusaway.services.async.ReportProblemWithTripServiceAsyncImpl
+import org.onebusaway.services.async.RouteIdsForAgencyServiceAsync
+import org.onebusaway.services.async.RouteIdsForAgencyServiceAsyncImpl
+import org.onebusaway.services.async.RouteServiceAsync
+import org.onebusaway.services.async.RouteServiceAsyncImpl
+import org.onebusaway.services.async.RoutesForAgencyServiceAsync
+import org.onebusaway.services.async.RoutesForAgencyServiceAsyncImpl
+import org.onebusaway.services.async.RoutesForLocationServiceAsync
+import org.onebusaway.services.async.RoutesForLocationServiceAsyncImpl
+import org.onebusaway.services.async.ScheduleForRouteServiceAsync
+import org.onebusaway.services.async.ScheduleForRouteServiceAsyncImpl
+import org.onebusaway.services.async.ScheduleForStopServiceAsync
+import org.onebusaway.services.async.ScheduleForStopServiceAsyncImpl
+import org.onebusaway.services.async.SearchForRouteServiceAsync
+import org.onebusaway.services.async.SearchForRouteServiceAsyncImpl
+import org.onebusaway.services.async.SearchForStopServiceAsync
+import org.onebusaway.services.async.SearchForStopServiceAsyncImpl
+import org.onebusaway.services.async.ShapeServiceAsync
+import org.onebusaway.services.async.ShapeServiceAsyncImpl
+import org.onebusaway.services.async.StopIdsForAgencyServiceAsync
+import org.onebusaway.services.async.StopIdsForAgencyServiceAsyncImpl
+import org.onebusaway.services.async.StopServiceAsync
+import org.onebusaway.services.async.StopServiceAsyncImpl
+import org.onebusaway.services.async.StopsForAgencyServiceAsync
+import org.onebusaway.services.async.StopsForAgencyServiceAsyncImpl
+import org.onebusaway.services.async.StopsForLocationServiceAsync
+import org.onebusaway.services.async.StopsForLocationServiceAsyncImpl
+import org.onebusaway.services.async.StopsForRouteServiceAsync
+import org.onebusaway.services.async.StopsForRouteServiceAsyncImpl
+import org.onebusaway.services.async.TripDetailServiceAsync
+import org.onebusaway.services.async.TripDetailServiceAsyncImpl
+import org.onebusaway.services.async.TripForVehicleServiceAsync
+import org.onebusaway.services.async.TripForVehicleServiceAsyncImpl
+import org.onebusaway.services.async.TripServiceAsync
+import org.onebusaway.services.async.TripServiceAsyncImpl
+import org.onebusaway.services.async.TripsForLocationServiceAsync
+import org.onebusaway.services.async.TripsForLocationServiceAsyncImpl
+import org.onebusaway.services.async.TripsForRouteServiceAsync
+import org.onebusaway.services.async.TripsForRouteServiceAsyncImpl
+import org.onebusaway.services.async.VehiclesForAgencyServiceAsync
+import org.onebusaway.services.async.VehiclesForAgencyServiceAsyncImpl
+
+class OnebusawaySdkClientAsyncImpl(
private val clientOptions: ClientOptions,
) : OnebusawaySdkClientAsync {
private val clientOptionsWithUserAgent =
- if (clientOptions.headers.containsKey("User-Agent")) clientOptions
+ if (clientOptions.headers.names().contains("User-Agent")) clientOptions
else
clientOptions
.toBuilder()
@@ -188,4 +241,6 @@ constructor(
override fun block(): BlockServiceAsync = block
override fun shape(): ShapeServiceAsync = shape
+
+ override fun close() = clientOptions.httpClient.close()
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientImpl.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientImpl.kt
index 1183849..bcc58db 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientImpl.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/client/OnebusawaySdkClientImpl.kt
@@ -4,16 +4,69 @@ package org.onebusaway.client
import org.onebusaway.core.ClientOptions
import org.onebusaway.core.getPackageVersion
-import org.onebusaway.models.*
-import org.onebusaway.services.blocking.*
-
-class OnebusawaySdkClientImpl
-constructor(
+import org.onebusaway.services.blocking.AgenciesWithCoverageService
+import org.onebusaway.services.blocking.AgenciesWithCoverageServiceImpl
+import org.onebusaway.services.blocking.AgencyService
+import org.onebusaway.services.blocking.AgencyServiceImpl
+import org.onebusaway.services.blocking.ArrivalAndDepartureService
+import org.onebusaway.services.blocking.ArrivalAndDepartureServiceImpl
+import org.onebusaway.services.blocking.BlockService
+import org.onebusaway.services.blocking.BlockServiceImpl
+import org.onebusaway.services.blocking.ConfigService
+import org.onebusaway.services.blocking.ConfigServiceImpl
+import org.onebusaway.services.blocking.CurrentTimeService
+import org.onebusaway.services.blocking.CurrentTimeServiceImpl
+import org.onebusaway.services.blocking.ReportProblemWithStopService
+import org.onebusaway.services.blocking.ReportProblemWithStopServiceImpl
+import org.onebusaway.services.blocking.ReportProblemWithTripService
+import org.onebusaway.services.blocking.ReportProblemWithTripServiceImpl
+import org.onebusaway.services.blocking.RouteIdsForAgencyService
+import org.onebusaway.services.blocking.RouteIdsForAgencyServiceImpl
+import org.onebusaway.services.blocking.RouteService
+import org.onebusaway.services.blocking.RouteServiceImpl
+import org.onebusaway.services.blocking.RoutesForAgencyService
+import org.onebusaway.services.blocking.RoutesForAgencyServiceImpl
+import org.onebusaway.services.blocking.RoutesForLocationService
+import org.onebusaway.services.blocking.RoutesForLocationServiceImpl
+import org.onebusaway.services.blocking.ScheduleForRouteService
+import org.onebusaway.services.blocking.ScheduleForRouteServiceImpl
+import org.onebusaway.services.blocking.ScheduleForStopService
+import org.onebusaway.services.blocking.ScheduleForStopServiceImpl
+import org.onebusaway.services.blocking.SearchForRouteService
+import org.onebusaway.services.blocking.SearchForRouteServiceImpl
+import org.onebusaway.services.blocking.SearchForStopService
+import org.onebusaway.services.blocking.SearchForStopServiceImpl
+import org.onebusaway.services.blocking.ShapeService
+import org.onebusaway.services.blocking.ShapeServiceImpl
+import org.onebusaway.services.blocking.StopIdsForAgencyService
+import org.onebusaway.services.blocking.StopIdsForAgencyServiceImpl
+import org.onebusaway.services.blocking.StopService
+import org.onebusaway.services.blocking.StopServiceImpl
+import org.onebusaway.services.blocking.StopsForAgencyService
+import org.onebusaway.services.blocking.StopsForAgencyServiceImpl
+import org.onebusaway.services.blocking.StopsForLocationService
+import org.onebusaway.services.blocking.StopsForLocationServiceImpl
+import org.onebusaway.services.blocking.StopsForRouteService
+import org.onebusaway.services.blocking.StopsForRouteServiceImpl
+import org.onebusaway.services.blocking.TripDetailService
+import org.onebusaway.services.blocking.TripDetailServiceImpl
+import org.onebusaway.services.blocking.TripForVehicleService
+import org.onebusaway.services.blocking.TripForVehicleServiceImpl
+import org.onebusaway.services.blocking.TripService
+import org.onebusaway.services.blocking.TripServiceImpl
+import org.onebusaway.services.blocking.TripsForLocationService
+import org.onebusaway.services.blocking.TripsForLocationServiceImpl
+import org.onebusaway.services.blocking.TripsForRouteService
+import org.onebusaway.services.blocking.TripsForRouteServiceImpl
+import org.onebusaway.services.blocking.VehiclesForAgencyService
+import org.onebusaway.services.blocking.VehiclesForAgencyServiceImpl
+
+class OnebusawaySdkClientImpl(
private val clientOptions: ClientOptions,
) : OnebusawaySdkClient {
private val clientOptionsWithUserAgent =
- if (clientOptions.headers.containsKey("User-Agent")) clientOptions
+ if (clientOptions.headers.names().contains("User-Agent")) clientOptions
else
clientOptions
.toBuilder()
@@ -180,4 +233,6 @@ constructor(
override fun block(): BlockService = block
override fun shape(): ShapeService = shape
+
+ override fun close() = clientOptions.httpClient.close()
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Check.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Check.kt
new file mode 100644
index 0000000..b6fd22d
--- /dev/null
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Check.kt
@@ -0,0 +1,29 @@
+@file:JvmName("Check")
+
+package org.onebusaway.core
+
+fun checkRequired(name: String, value: T?): T =
+ checkNotNull(value) { "`$name` is required, but was not set" }
+
+@JvmSynthetic
+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}" }
+ }
+
+@JvmSynthetic
+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}"
+ }
+ }
+
+@JvmSynthetic
+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}"
+ }
+ }
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/ClientOptions.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/ClientOptions.kt
index 370b3f4..2e214a5 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/ClientOptions.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/ClientOptions.kt
@@ -3,11 +3,11 @@
package org.onebusaway.core
import com.fasterxml.jackson.databind.json.JsonMapper
-import com.google.common.collect.ArrayListMultimap
-import com.google.common.collect.ListMultimap
import java.time.Clock
+import org.onebusaway.core.http.Headers
import org.onebusaway.core.http.HttpClient
import org.onebusaway.core.http.PhantomReachableClosingHttpClient
+import org.onebusaway.core.http.QueryParams
import org.onebusaway.core.http.RetryingHttpClient
class ClientOptions
@@ -17,8 +17,8 @@ private constructor(
@get:JvmName("jsonMapper") val jsonMapper: JsonMapper,
@get:JvmName("clock") val clock: Clock,
@get:JvmName("baseUrl") val baseUrl: String,
- @get:JvmName("headers") val headers: ListMultimap,
- @get:JvmName("queryParams") val queryParams: ListMultimap,
+ @get:JvmName("headers") val headers: Headers,
+ @get:JvmName("queryParams") val queryParams: QueryParams,
@get:JvmName("responseValidation") val responseValidation: Boolean,
@get:JvmName("maxRetries") val maxRetries: Int,
@get:JvmName("apiKey") val apiKey: String,
@@ -35,14 +35,15 @@ private constructor(
@JvmStatic fun fromEnv(): ClientOptions = builder().fromEnv().build()
}
- class Builder {
+ /** A builder for [ClientOptions]. */
+ class Builder internal constructor() {
private var httpClient: HttpClient? = null
private var jsonMapper: JsonMapper = jsonMapper()
private var clock: Clock = Clock.systemUTC()
private var baseUrl: String = PRODUCTION_URL
- private var headers: ListMultimap = ArrayListMultimap.create()
- private var queryParams: ListMultimap = ArrayListMultimap.create()
+ private var headers: Headers.Builder = Headers.builder()
+ private var queryParams: QueryParams.Builder = QueryParams.builder()
private var responseValidation: Boolean = false
private var maxRetries: Int = 2
private var apiKey: String? = null
@@ -53,8 +54,8 @@ private constructor(
jsonMapper = clientOptions.jsonMapper
clock = clientOptions.clock
baseUrl = clientOptions.baseUrl
- headers = ArrayListMultimap.create(clientOptions.headers)
- queryParams = ArrayListMultimap.create(clientOptions.queryParams)
+ headers = clientOptions.headers.toBuilder()
+ queryParams = clientOptions.queryParams.toBuilder()
responseValidation = clientOptions.responseValidation
maxRetries = clientOptions.maxRetries
apiKey = clientOptions.apiKey
@@ -68,6 +69,19 @@ private constructor(
fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl }
+ fun responseValidation(responseValidation: Boolean) = apply {
+ this.responseValidation = responseValidation
+ }
+
+ 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)
@@ -75,29 +89,34 @@ private constructor(
fun putHeader(name: String, value: String) = apply { headers.put(name, value) }
- fun putHeaders(name: String, values: Iterable) = apply {
- headers.putAll(name, values)
- }
+ 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 {
- headers.forEach(::putHeaders)
+ this.headers.putAll(headers)
}
- fun replaceHeaders(name: String, value: String) = apply {
- headers.replaceValues(name, listOf(value))
- }
+ fun replaceHeaders(name: String, value: String) = apply { headers.replace(name, value) }
fun replaceHeaders(name: String, values: Iterable) = apply {
- headers.replaceValues(name, values)
+ headers.replace(name, values)
}
+ fun replaceAllHeaders(headers: Headers) = apply { this.headers.replaceAll(headers) }
+
fun replaceAllHeaders(headers: Map>) = apply {
- headers.forEach(::replaceHeaders)
+ this.headers.replaceAll(headers)
}
- fun removeHeaders(name: String) = apply { headers.removeAll(name) }
+ fun removeHeaders(name: String) = apply { headers.remove(name) }
+
+ fun removeAllHeaders(names: Set) = apply { headers.removeAll(names) }
- fun removeAllHeaders(names: Set) = apply { names.forEach(::removeHeaders) }
+ fun queryParams(queryParams: QueryParams) = apply {
+ this.queryParams.clear()
+ putAllQueryParams(queryParams)
+ }
fun queryParams(queryParams: Map>) = apply {
this.queryParams.clear()
@@ -107,45 +126,45 @@ private constructor(
fun putQueryParam(key: String, value: String) = apply { queryParams.put(key, value) }
fun putQueryParams(key: String, values: Iterable) = apply {
- queryParams.putAll(key, values)
+ queryParams.put(key, values)
+ }
+
+ fun putAllQueryParams(queryParams: QueryParams) = apply {
+ this.queryParams.putAll(queryParams)
}
fun putAllQueryParams(queryParams: Map>) = apply {
- queryParams.forEach(::putQueryParams)
+ this.queryParams.putAll(queryParams)
}
fun replaceQueryParams(key: String, value: String) = apply {
- queryParams.replaceValues(key, listOf(value))
+ queryParams.replace(key, value)
}
fun replaceQueryParams(key: String, values: Iterable) = apply {
- queryParams.replaceValues(key, values)
+ queryParams.replace(key, values)
}
- fun replaceAllQueryParams(queryParams: Map>) = apply {
- queryParams.forEach(::replaceQueryParams)
+ fun replaceAllQueryParams(queryParams: QueryParams) = apply {
+ this.queryParams.replaceAll(queryParams)
}
- fun removeQueryParams(key: String) = apply { queryParams.removeAll(key) }
-
- fun removeAllQueryParams(keys: Set) = apply { keys.forEach(::removeQueryParams) }
-
- fun responseValidation(responseValidation: Boolean) = apply {
- this.responseValidation = responseValidation
+ fun replaceAllQueryParams(queryParams: Map>) = apply {
+ this.queryParams.replaceAll(queryParams)
}
- fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries }
+ fun removeQueryParams(key: String) = apply { queryParams.remove(key) }
- fun apiKey(apiKey: String) = apply { this.apiKey = apiKey }
+ fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) }
fun fromEnv() = apply { System.getenv("ONEBUSAWAY_API_KEY")?.let { apiKey(it) } }
fun build(): ClientOptions {
- checkNotNull(httpClient) { "`httpClient` is required but was not set" }
- checkNotNull(apiKey) { "`apiKey` is required but was not set" }
+ val httpClient = checkRequired("httpClient", httpClient)
+ val apiKey = checkRequired("apiKey", apiKey)
- val headers = ArrayListMultimap.create()
- val queryParams = ArrayListMultimap.create()
+ val headers = Headers.builder()
+ val queryParams = QueryParams.builder()
headers.put("X-Stainless-Lang", "java")
headers.put("X-Stainless-Arch", getOsArch())
headers.put("X-Stainless-OS", getOsName())
@@ -153,17 +172,19 @@ private constructor(
headers.put("X-Stainless-Package-Version", getPackageVersion())
headers.put("X-Stainless-Runtime", "JRE")
headers.put("X-Stainless-Runtime-Version", getJavaVersion())
- if (!apiKey.isNullOrEmpty()) {
- queryParams.put("key", apiKey)
+ apiKey.let {
+ if (!it.isEmpty()) {
+ headers.put("key", it)
+ }
}
- this.headers.asMap().forEach(headers::replaceValues)
- this.queryParams.asMap().forEach(queryParams::replaceValues)
+ headers.replaceAll(this.headers.build())
+ queryParams.replaceAll(this.queryParams.build())
return ClientOptions(
- httpClient!!,
+ httpClient,
PhantomReachableClosingHttpClient(
RetryingHttpClient.builder()
- .httpClient(httpClient!!)
+ .httpClient(httpClient)
.clock(clock)
.maxRetries(maxRetries)
.build()
@@ -171,11 +192,11 @@ private constructor(
jsonMapper,
clock,
baseUrl,
- headers.toImmutable(),
- queryParams.toImmutable(),
+ headers.build(),
+ queryParams.build(),
responseValidation,
maxRetries,
- apiKey!!,
+ apiKey,
)
}
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Params.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Params.kt
new file mode 100644
index 0000000..48d18a8
--- /dev/null
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Params.kt
@@ -0,0 +1,16 @@
+package org.onebusaway.core
+
+import org.onebusaway.core.http.Headers
+import org.onebusaway.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/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/PhantomReachable.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/PhantomReachable.kt
index e35ca9a..8391e58 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/PhantomReachable.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/PhantomReachable.kt
@@ -15,10 +15,20 @@ 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?.let { it(observed, closeable::close) }
+ closeWhenPhantomReachable(observed, closeable::close)
}
-private val closeWhenPhantomReachable: ((Any, AutoCloseable) -> Unit)? by lazy {
+/**
+ * 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.
+ */
+@JvmSynthetic
+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")
@@ -26,9 +36,9 @@ private val closeWhenPhantomReachable: ((Any, AutoCloseable) -> Unit)? by lazy {
cleanerClass.getMethod("register", Any::class.java, Runnable::class.java)
val cleanerObject = cleanerCreate.invoke(null);
- { observed, closeable ->
+ { observed, close ->
try {
- cleanerRegister.invoke(cleanerObject, observed, Runnable { closeable.close() })
+ cleanerRegister.invoke(cleanerObject, observed, Runnable { close() })
} catch (e: ReflectiveOperationException) {
if (e is InvocationTargetException) {
when (val cause = e.cause) {
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/PrepareRequest.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/PrepareRequest.kt
new file mode 100644
index 0000000..b78d6b6
--- /dev/null
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/PrepareRequest.kt
@@ -0,0 +1,24 @@
+@file:JvmName("PrepareRequest")
+
+package org.onebusaway.core
+
+import java.util.concurrent.CompletableFuture
+import org.onebusaway.core.http.HttpRequest
+
+@JvmSynthetic
+internal fun HttpRequest.prepare(clientOptions: ClientOptions, params: Params): HttpRequest =
+ toBuilder()
+ .putAllQueryParams(clientOptions.queryParams)
+ .replaceAllQueryParams(params._queryParams())
+ .putAllHeaders(clientOptions.headers)
+ .replaceAllHeaders(params._headers())
+ .build()
+
+@JvmSynthetic
+internal fun HttpRequest.prepareAsync(
+ clientOptions: ClientOptions,
+ params: Params
+): CompletableFuture =
+ // This async version exists to make it easier to add async specific preparation logic in the
+ // future.
+ CompletableFuture.completedFuture(prepare(clientOptions, params))
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/RequestOptions.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/RequestOptions.kt
index ec2f645..653da53 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/RequestOptions.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/RequestOptions.kt
@@ -23,7 +23,8 @@ private constructor(
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ class Builder internal constructor() {
+
private var responseValidation: Boolean? = null
private var timeout: Duration? = null
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Utils.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Utils.kt
index 4ccb63c..31e1d87 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Utils.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Utils.kt
@@ -2,8 +2,6 @@
package org.onebusaway.core
-import com.google.common.collect.ImmutableListMultimap
-import com.google.common.collect.ListMultimap
import java.util.Collections
import java.util.SortedMap
import org.onebusaway.errors.OnebusawaySdkInvalidDataException
@@ -18,15 +16,13 @@ internal fun List.toImmutable(): List =
@JvmSynthetic
internal fun Map.toImmutable(): Map =
- if (isEmpty()) Collections.emptyMap() else Collections.unmodifiableMap(toMap())
+ if (isEmpty()) immutableEmptyMap() else Collections.unmodifiableMap(toMap())
+
+@JvmSynthetic internal fun immutableEmptyMap(): Map = Collections.emptyMap()
@JvmSynthetic
internal fun , V> SortedMap.toImmutable(): SortedMap =
if (isEmpty()) Collections.emptySortedMap()
else Collections.unmodifiableSortedMap(toSortedMap(comparator()))
-@JvmSynthetic
-internal fun ListMultimap.toImmutable(): ListMultimap =
- ImmutableListMultimap.copyOf(this)
-
internal interface Enum
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Values.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Values.kt
index f5d6cde..387b30b 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Values.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/Values.kt
@@ -119,6 +119,8 @@ sealed class JsonField {
is JsonValue -> this
}
+ @JvmSynthetic fun accept(consume: (T) -> Unit) = asKnown().ifPresent(consume)
+
fun accept(visitor: Visitor): R =
when (this) {
is KnownValue -> visitor.visitKnown(value)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/handlers/ErrorHandler.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/handlers/ErrorHandler.kt
index f7938ba..621d820 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/handlers/ErrorHandler.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/handlers/ErrorHandler.kt
@@ -3,9 +3,9 @@
package org.onebusaway.core.handlers
import com.fasterxml.jackson.databind.json.JsonMapper
-import com.google.common.collect.ListMultimap
import java.io.ByteArrayInputStream
import java.io.InputStream
+import org.onebusaway.core.http.Headers
import org.onebusaway.core.http.HttpResponse
import org.onebusaway.core.http.HttpResponse.Handler
import org.onebusaway.errors.BadRequestException
@@ -118,7 +118,7 @@ private fun HttpResponse.buffered(): HttpResponse {
return object : HttpResponse {
override fun statusCode(): Int = this@buffered.statusCode()
- override fun headers(): ListMultimap = this@buffered.headers()
+ override fun headers(): Headers = this@buffered.headers()
override fun body(): InputStream = ByteArrayInputStream(body)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/Headers.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/Headers.kt
index 1e17303..e6f6448 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/Headers.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/Headers.kt
@@ -22,7 +22,7 @@ private constructor(
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ class Builder internal constructor() {
private val map: MutableMap> =
TreeMap(String.CASE_INSENSITIVE_ORDER)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpRequest.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpRequest.kt
index 9139930..1b4396b 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpRequest.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpRequest.kt
@@ -1,8 +1,6 @@
package org.onebusaway.core.http
-import com.google.common.collect.ArrayListMultimap
-import com.google.common.collect.ListMultimap
-import com.google.common.collect.MultimapBuilder
+import org.onebusaway.core.checkRequired
import org.onebusaway.core.toImmutable
class HttpRequest
@@ -10,11 +8,13 @@ private constructor(
@get:JvmName("method") val method: HttpMethod,
@get:JvmName("url") val url: String?,
@get:JvmName("pathSegments") val pathSegments: List,
- @get:JvmName("headers") val headers: ListMultimap,
- @get:JvmName("queryParams") val queryParams: ListMultimap,
+ @get:JvmName("headers") val headers: Headers,
+ @get:JvmName("queryParams") val queryParams: QueryParams,
@get:JvmName("body") val body: HttpRequestBody?,
) {
+ fun toBuilder(): Builder = Builder().from(this)
+
override fun toString(): String =
"HttpRequest{method=$method, url=$url, pathSegments=$pathSegments, headers=$headers, queryParams=$queryParams, body=$body}"
@@ -22,16 +22,25 @@ private constructor(
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ class Builder internal constructor() {
private var method: HttpMethod? = null
private var url: String? = null
private var pathSegments: MutableList = mutableListOf()
- private var headers: ListMultimap =
- MultimapBuilder.treeKeys(String.CASE_INSENSITIVE_ORDER).arrayListValues().build()
- private var queryParams: ListMultimap = ArrayListMultimap.create()
+ private var headers: Headers.Builder = Headers.builder()
+ private var queryParams: QueryParams.Builder = QueryParams.builder()
private var body: HttpRequestBody? = null
+ @JvmSynthetic
+ internal fun from(request: HttpRequest) = apply {
+ method = request.method
+ url = request.url
+ pathSegments = request.pathSegments.toMutableList()
+ headers = request.headers.toBuilder()
+ queryParams = request.queryParams.toBuilder()
+ body = request.body
+ }
+
fun method(method: HttpMethod) = apply { this.method = method }
fun url(url: String) = apply { this.url = url }
@@ -42,6 +51,11 @@ private constructor(
this.pathSegments.addAll(pathSegments)
}
+ fun headers(headers: Headers) = apply {
+ this.headers.clear()
+ putAllHeaders(headers)
+ }
+
fun headers(headers: Map>) = apply {
this.headers.clear()
putAllHeaders(headers)
@@ -49,29 +63,34 @@ private constructor(
fun putHeader(name: String, value: String) = apply { headers.put(name, value) }
- fun putHeaders(name: String, values: Iterable) = apply {
- headers.putAll(name, values)
- }
+ 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 {
- headers.forEach(::putHeaders)
+ this.headers.putAll(headers)
}
- fun replaceHeaders(name: String, value: String) = apply {
- headers.replaceValues(name, listOf(value))
- }
+ fun replaceHeaders(name: String, value: String) = apply { headers.replace(name, value) }
fun replaceHeaders(name: String, values: Iterable) = apply {
- headers.replaceValues(name, values)
+ headers.replace(name, values)
}
+ fun replaceAllHeaders(headers: Headers) = apply { this.headers.replaceAll(headers) }
+
fun replaceAllHeaders(headers: Map>) = apply {
- headers.forEach(::replaceHeaders)
+ this.headers.replaceAll(headers)
}
- fun removeHeaders(name: String) = apply { headers.removeAll(name) }
+ fun removeHeaders(name: String) = apply { headers.remove(name) }
+
+ fun removeAllHeaders(names: Set) = apply { headers.removeAll(names) }
- fun removeAllHeaders(names: Set) = apply { names.forEach(::removeHeaders) }
+ fun queryParams(queryParams: QueryParams) = apply {
+ this.queryParams.clear()
+ putAllQueryParams(queryParams)
+ }
fun queryParams(queryParams: Map>) = apply {
this.queryParams.clear()
@@ -81,38 +100,46 @@ private constructor(
fun putQueryParam(key: String, value: String) = apply { queryParams.put(key, value) }
fun putQueryParams(key: String, values: Iterable) = apply {
- queryParams.putAll(key, values)
+ queryParams.put(key, values)
+ }
+
+ fun putAllQueryParams(queryParams: QueryParams) = apply {
+ this.queryParams.putAll(queryParams)
}
fun putAllQueryParams(queryParams: Map>) = apply {
- queryParams.forEach(::putQueryParams)
+ this.queryParams.putAll(queryParams)
}
fun replaceQueryParams(key: String, value: String) = apply {
- queryParams.replaceValues(key, listOf(value))
+ queryParams.replace(key, value)
}
fun replaceQueryParams(key: String, values: Iterable) = apply {
- queryParams.replaceValues(key, values)
+ queryParams.replace(key, values)
+ }
+
+ fun replaceAllQueryParams(queryParams: QueryParams) = apply {
+ this.queryParams.replaceAll(queryParams)
}
fun replaceAllQueryParams(queryParams: Map>) = apply {
- queryParams.forEach(::replaceQueryParams)
+ this.queryParams.replaceAll(queryParams)
}
- fun removeQueryParams(key: String) = apply { queryParams.removeAll(key) }
+ fun removeQueryParams(key: String) = apply { queryParams.remove(key) }
- fun removeAllQueryParams(keys: Set) = apply { keys.forEach(::removeQueryParams) }
+ fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) }
fun body(body: HttpRequestBody) = apply { this.body = body }
fun build(): HttpRequest =
HttpRequest(
- checkNotNull(method) { "`method` is required but was not set" },
+ checkRequired("method", method),
url,
pathSegments.toImmutable(),
- headers,
- queryParams.toImmutable(),
+ headers.build(),
+ queryParams.build(),
body,
)
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpResponse.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpResponse.kt
index b2870ca..1a3f27d 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpResponse.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/HttpResponse.kt
@@ -1,6 +1,5 @@
package org.onebusaway.core.http
-import com.google.common.collect.ListMultimap
import java.io.InputStream
import java.lang.AutoCloseable
@@ -8,7 +7,7 @@ interface HttpResponse : AutoCloseable {
fun statusCode(): Int
- fun headers(): ListMultimap
+ fun headers(): Headers
fun body(): InputStream
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/PhantomReachableClosingHttpClient.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/PhantomReachableClosingHttpClient.kt
index f923a21..756f8a2 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/PhantomReachableClosingHttpClient.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/PhantomReachableClosingHttpClient.kt
@@ -4,6 +4,11 @@ import java.util.concurrent.CompletableFuture
import org.onebusaway.core.RequestOptions
import org.onebusaway.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)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/QueryParams.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/QueryParams.kt
index a5e7ddf..1e9bbb7 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/QueryParams.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/QueryParams.kt
@@ -21,7 +21,7 @@ private constructor(
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ class Builder internal constructor() {
private val map: MutableMap> = mutableMapOf()
private var size: Int = 0
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/RetryingHttpClient.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/RetryingHttpClient.kt
index 37bc637..eb4f5ed 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/RetryingHttpClient.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/core/http/RetryingHttpClient.kt
@@ -17,6 +17,7 @@ import java.util.function.Function
import kotlin.math.min
import kotlin.math.pow
import org.onebusaway.core.RequestOptions
+import org.onebusaway.core.checkRequired
import org.onebusaway.errors.OnebusawaySdkIoException
class RetryingHttpClient
@@ -35,35 +36,38 @@ private constructor(
return httpClient.execute(request, requestOptions)
}
- maybeAddIdempotencyHeader(request)
+ var modifiedRequest = maybeAddIdempotencyHeader(request)
// Don't send the current retry count in the headers if the caller set their own value.
- val shouldSendRetryCount = !request.headers.containsKey("x-stainless-retry-count")
+ val shouldSendRetryCount =
+ !modifiedRequest.headers.names().contains("X-Stainless-Retry-Count")
var retries = 0
while (true) {
if (shouldSendRetryCount) {
- setRetryCountHeader(request, retries)
+ modifiedRequest = setRetryCountHeader(modifiedRequest, retries)
}
val response =
try {
- val response = httpClient.execute(request, requestOptions)
+ val response = httpClient.execute(modifiedRequest, requestOptions)
if (++retries > maxRetries || !shouldRetry(response)) {
return response
}
response
- } catch (t: Throwable) {
- if (++retries > maxRetries || !shouldRetry(t)) {
- throw t
+ } catch (throwable: Throwable) {
+ if (++retries > maxRetries || !shouldRetry(throwable)) {
+ throw throwable
}
null
}
val backoffMillis = getRetryBackoffMillis(retries, response)
+ // All responses must be closed, so close the failed one before retrying.
+ response?.close()
Thread.sleep(backoffMillis.toMillis())
}
}
@@ -76,10 +80,11 @@ private constructor(
return httpClient.executeAsync(request, requestOptions)
}
- maybeAddIdempotencyHeader(request)
+ val modifiedRequest = maybeAddIdempotencyHeader(request)
// Don't send the current retry count in the headers if the caller set their own value.
- val shouldSendRetryCount = !request.headers.containsKey("x-stainless-retry-count")
+ val shouldSendRetryCount =
+ !modifiedRequest.headers.names().contains("X-Stainless-Retry-Count")
var retries = 0
@@ -87,12 +92,11 @@ private constructor(
request: HttpRequest,
requestOptions: RequestOptions,
): CompletableFuture {
- if (shouldSendRetryCount) {
- setRetryCountHeader(request, retries)
- }
+ val requestWithRetryCount =
+ if (shouldSendRetryCount) setRetryCountHeader(request, retries) else request
return httpClient
- .executeAsync(request, requestOptions)
+ .executeAsync(requestWithRetryCount, requestOptions)
.handleAsync(
fun(
response: HttpResponse?,
@@ -111,8 +115,10 @@ private constructor(
}
val backoffMillis = getRetryBackoffMillis(retries, response)
+ // All responses must be closed, so close the failed one before retrying.
+ response?.close()
return sleepAsync(backoffMillis.toMillis()).thenCompose {
- executeWithRetries(request, requestOptions)
+ executeWithRetries(requestWithRetryCount, requestOptions)
}
},
) {
@@ -122,7 +128,7 @@ private constructor(
.thenCompose(Function.identity())
}
- return executeWithRetries(request, requestOptions)
+ return executeWithRetries(modifiedRequest, requestOptions)
}
override fun close() = httpClient.close()
@@ -132,23 +138,26 @@ private constructor(
// the body data aren't available on subsequent attempts.
request.body?.repeatable() ?: true
- private fun setRetryCountHeader(request: HttpRequest, retries: Int) {
- request.headers.removeAll("x-stainless-retry-count")
- request.headers.put("x-stainless-retry-count", retries.toString())
- }
+ 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) {
- if (idempotencyHeader != null && !request.headers.containsKey(idempotencyHeader)) {
- // Set a header to uniquely identify the request when retried
- request.headers.put(idempotencyHeader, idempotencyKey())
+ 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().get("x-should-retry").getOrNull(0)
+ val shouldRetryHeader = response.headers().values("X-Should-Retry").getOrNull(0)
val statusCode = response.statusCode()
return when {
@@ -181,11 +190,11 @@ private constructor(
?.headers()
?.let { headers ->
headers
- .get("Retry-After-Ms")
+ .values("Retry-After-Ms")
.getOrNull(0)
?.toFloatOrNull()
?.times(TimeUnit.MILLISECONDS.toNanos(1))
- ?: headers.get("Retry-After").getOrNull(0)?.let { retryAfter ->
+ ?: headers.values("Retry-After").getOrNull(0)?.let { retryAfter ->
retryAfter.toFloatOrNull()?.times(TimeUnit.SECONDS.toNanos(1))
?: try {
ChronoUnit.MILLIS.between(
@@ -219,27 +228,27 @@ private constructor(
return Duration.ofNanos((TimeUnit.SECONDS.toNanos(1) * backoffSeconds * jitter).toLong())
}
- private fun sleepAsync(millis: Long): CompletableFuture {
- val future = CompletableFuture()
- TIMER.schedule(
- object : TimerTask() {
- override fun run() {
- future.complete(null)
- }
- },
- millis
- )
- return future
- }
-
companion object {
private val TIMER = Timer("RetryingHttpClient", true)
+ private fun sleepAsync(millis: Long): CompletableFuture {
+ val future = CompletableFuture()
+ TIMER.schedule(
+ object : TimerTask() {
+ override fun run() {
+ future.complete(null)
+ }
+ },
+ millis
+ )
+ return future
+ }
+
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ class Builder internal constructor() {
private var httpClient: HttpClient? = null
private var clock: Clock = Clock.systemUTC()
@@ -256,7 +265,7 @@ private constructor(
fun build(): HttpClient =
RetryingHttpClient(
- checkNotNull(httpClient) { "`httpClient` is required but was not set" },
+ checkRequired("httpClient", httpClient),
clock,
maxRetries,
idempotencyHeader,
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/BadRequestException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/BadRequestException.kt
index dee8196..036562b 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/BadRequestException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/BadRequestException.kt
@@ -1,9 +1,9 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class BadRequestException(
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(400, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/InternalServerException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/InternalServerException.kt
index 5c3229f..b99d5f0 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/InternalServerException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/InternalServerException.kt
@@ -1,10 +1,10 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class InternalServerException(
statusCode: Int,
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(statusCode, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/NotFoundException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/NotFoundException.kt
index 35e69c4..d7215fd 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/NotFoundException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/NotFoundException.kt
@@ -1,9 +1,9 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class NotFoundException(
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(404, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkError.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkError.kt
index 6f0a191..bf85359 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkError.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkError.kt
@@ -4,64 +4,73 @@ package org.onebusaway.errors
import com.fasterxml.jackson.annotation.JsonAnyGetter
import com.fasterxml.jackson.annotation.JsonAnySetter
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize
+import com.fasterxml.jackson.annotation.JsonCreator
import java.util.Objects
+import org.onebusaway.core.ExcludeMissing
import org.onebusaway.core.JsonValue
import org.onebusaway.core.NoAutoDetect
+import org.onebusaway.core.immutableEmptyMap
import org.onebusaway.core.toImmutable
-@JsonDeserialize(builder = OnebusawaySdkError.Builder::class)
@NoAutoDetect
class OnebusawaySdkError
-constructor(
- private val additionalProperties: Map,
+@JsonCreator
+private constructor(
+ @JsonAnyGetter
+ @ExcludeMissing
+ @JsonAnySetter
+ @get:JvmName("additionalProperties")
+ val additionalProperties: Map = immutableEmptyMap(),
) {
- @JsonAnyGetter fun additionalProperties(): Map = additionalProperties
-
- fun toBuilder() = Builder()
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return /* spotless:off */ other is OnebusawaySdkError && this.additionalProperties == other.additionalProperties /* spotless:on */
- }
-
- override fun hashCode(): Int {
- return /* spotless:off */ Objects.hash(additionalProperties) /* spotless:on */
- }
-
- override fun toString() = "OnebusawaySdkError{additionalProperties=$additionalProperties}"
+ fun toBuilder() = Builder().from(this)
companion object {
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ /** A builder for [OnebusawaySdkError]. */
+ class Builder internal constructor() {
private var additionalProperties: MutableMap = mutableMapOf()
- fun from(error: OnebusawaySdkError) = apply {
- additionalProperties(error.additionalProperties)
+ @JvmSynthetic
+ internal fun from(onebusawaySdkError: OnebusawaySdkError) = apply {
+ additionalProperties = onebusawaySdkError.additionalProperties.toMutableMap()
}
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
- this.additionalProperties.putAll(additionalProperties)
+ putAllAdditionalProperties(additionalProperties)
}
- @JsonAnySetter
fun putAdditionalProperty(key: String, value: JsonValue) = apply {
- this.additionalProperties.put(key, value)
+ 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)
+ }
+
fun build(): OnebusawaySdkError = OnebusawaySdkError(additionalProperties.toImmutable())
}
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return /* spotless:off */ other is OnebusawaySdkError && additionalProperties == other.additionalProperties /* spotless:on */
+ }
+
+ override fun hashCode(): Int = /* spotless:off */ Objects.hash(additionalProperties) /* spotless:on */
+
+ override fun toString() = "OnebusawaySdkError{additionalProperties=$additionalProperties}"
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkServiceException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkServiceException.kt
index 96d7d2d..e65331d 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkServiceException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/OnebusawaySdkServiceException.kt
@@ -1,12 +1,12 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
abstract class OnebusawaySdkServiceException
@JvmOverloads
constructor(
private val statusCode: Int,
- private val headers: ListMultimap,
+ private val headers: Headers,
private val body: String,
private val error: OnebusawaySdkError,
message: String = "$statusCode: $error",
@@ -15,7 +15,7 @@ constructor(
fun statusCode(): Int = statusCode
- fun headers(): ListMultimap = headers
+ fun headers(): Headers = headers
fun body(): String = body
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/PermissionDeniedException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/PermissionDeniedException.kt
index bb06e6a..7c70b0b 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/PermissionDeniedException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/PermissionDeniedException.kt
@@ -1,9 +1,9 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class PermissionDeniedException(
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(403, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/RateLimitException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/RateLimitException.kt
index c210a32..314ad3b 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/RateLimitException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/RateLimitException.kt
@@ -1,9 +1,9 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class RateLimitException(
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(429, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnauthorizedException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnauthorizedException.kt
index dc34495..7b6a7a3 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnauthorizedException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnauthorizedException.kt
@@ -1,9 +1,9 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class UnauthorizedException(
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(401, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnexpectedStatusCodeException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnexpectedStatusCodeException.kt
index a54c02d..192fed6 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnexpectedStatusCodeException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnexpectedStatusCodeException.kt
@@ -1,10 +1,10 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class UnexpectedStatusCodeException(
statusCode: Int,
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(statusCode, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnprocessableEntityException.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnprocessableEntityException.kt
index a30211a..bc0e0a7 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnprocessableEntityException.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/errors/UnprocessableEntityException.kt
@@ -1,9 +1,9 @@
package org.onebusaway.errors
-import com.google.common.collect.ListMultimap
+import org.onebusaway.core.http.Headers
class UnprocessableEntityException(
- headers: ListMultimap,
+ headers: Headers,
body: String,
error: OnebusawaySdkError,
) : OnebusawaySdkServiceException(422, headers, body, error)
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListParams.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListParams.kt
index 6e8ed63..ed0199c 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListParams.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListParams.kt
@@ -2,41 +2,29 @@
package org.onebusaway.models
-import com.google.common.collect.ArrayListMultimap
-import com.google.common.collect.ListMultimap
import java.util.Objects
import org.onebusaway.core.NoAutoDetect
-import org.onebusaway.core.toImmutable
-import org.onebusaway.models.*
-
+import org.onebusaway.core.Params
+import org.onebusaway.core.http.Headers
+import org.onebusaway.core.http.QueryParams
+
+/**
+ * Returns a list of all transit agencies currently supported by OneBusAway along with the center of
+ * their coverage area.
+ */
class AgenciesWithCoverageListParams
-constructor(
- private val additionalHeaders: Map>,
- private val additionalQueryParams: Map>,
-) {
-
- @JvmSynthetic internal fun getHeaders(): Map> = additionalHeaders
+private constructor(
+ private val additionalHeaders: Headers,
+ private val additionalQueryParams: QueryParams,
+) : Params {
- @JvmSynthetic internal fun getQueryParams(): Map> = additionalQueryParams
+ fun _additionalHeaders(): Headers = additionalHeaders
- fun _additionalHeaders(): Map> = additionalHeaders
+ fun _additionalQueryParams(): QueryParams = additionalQueryParams
- fun _additionalQueryParams(): Map> = additionalQueryParams
+ override fun _headers(): Headers = additionalHeaders
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return /* spotless:off */ other is AgenciesWithCoverageListParams && this.additionalHeaders == other.additionalHeaders && this.additionalQueryParams == other.additionalQueryParams /* spotless:on */
- }
-
- override fun hashCode(): Int {
- return /* spotless:off */ Objects.hash(additionalHeaders, additionalQueryParams) /* spotless:on */
- }
-
- override fun toString() =
- "AgenciesWithCoverageListParams{additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
+ override fun _queryParams(): QueryParams = additionalQueryParams
fun toBuilder() = Builder().from(this)
@@ -45,16 +33,22 @@ constructor(
@JvmStatic fun builder() = Builder()
}
+ /** A builder for [AgenciesWithCoverageListParams]. */
@NoAutoDetect
- class Builder {
+ class Builder internal constructor() {
- private var additionalHeaders: ListMultimap = ArrayListMultimap.create()
- private var additionalQueryParams: ListMultimap = ArrayListMultimap.create()
+ private var additionalHeaders: Headers.Builder = Headers.builder()
+ private var additionalQueryParams: QueryParams.Builder = QueryParams.builder()
@JvmSynthetic
internal fun from(agenciesWithCoverageListParams: AgenciesWithCoverageListParams) = apply {
- additionalHeaders(agenciesWithCoverageListParams.additionalHeaders)
- additionalQueryParams(agenciesWithCoverageListParams.additionalQueryParams)
+ additionalHeaders = agenciesWithCoverageListParams.additionalHeaders.toBuilder()
+ additionalQueryParams = agenciesWithCoverageListParams.additionalQueryParams.toBuilder()
+ }
+
+ fun additionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.clear()
+ putAllAdditionalHeaders(additionalHeaders)
}
fun additionalHeaders(additionalHeaders: Map>) = apply {
@@ -67,29 +61,42 @@ constructor(
}
fun putAdditionalHeaders(name: String, values: Iterable) = apply {
- additionalHeaders.putAll(name, values)
+ additionalHeaders.put(name, values)
+ }
+
+ fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.putAll(additionalHeaders)
}
fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply {
- additionalHeaders.forEach(::putAdditionalHeaders)
+ this.additionalHeaders.putAll(additionalHeaders)
}
fun replaceAdditionalHeaders(name: String, value: String) = apply {
- additionalHeaders.replaceValues(name, listOf(value))
+ additionalHeaders.replace(name, value)
}
fun replaceAdditionalHeaders(name: String, values: Iterable) = apply {
- additionalHeaders.replaceValues(name, values)
+ additionalHeaders.replace(name, values)
+ }
+
+ fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.replaceAll(additionalHeaders)
}
fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply {
- additionalHeaders.forEach(::replaceAdditionalHeaders)
+ this.additionalHeaders.replaceAll(additionalHeaders)
}
- fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.removeAll(name) }
+ fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) }
fun removeAllAdditionalHeaders(names: Set) = apply {
- names.forEach(::removeAdditionalHeaders)
+ additionalHeaders.removeAll(names)
+ }
+
+ fun additionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.clear()
+ putAllAdditionalQueryParams(additionalQueryParams)
}
fun additionalQueryParams(additionalQueryParams: Map>) = apply {
@@ -102,45 +109,55 @@ constructor(
}
fun putAdditionalQueryParams(key: String, values: Iterable) = apply {
- additionalQueryParams.putAll(key, values)
+ additionalQueryParams.put(key, values)
+ }
+
+ fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.putAll(additionalQueryParams)
}
fun putAllAdditionalQueryParams(additionalQueryParams: Map>) =
apply {
- additionalQueryParams.forEach(::putAdditionalQueryParams)
+ this.additionalQueryParams.putAll(additionalQueryParams)
}
fun replaceAdditionalQueryParams(key: String, value: String) = apply {
- additionalQueryParams.replaceValues(key, listOf(value))
+ additionalQueryParams.replace(key, value)
}
fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply {
- additionalQueryParams.replaceValues(key, values)
+ additionalQueryParams.replace(key, values)
+ }
+
+ fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.replaceAll(additionalQueryParams)
}
fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) =
apply {
- additionalQueryParams.forEach(::replaceAdditionalQueryParams)
+ this.additionalQueryParams.replaceAll(additionalQueryParams)
}
- fun removeAdditionalQueryParams(key: String) = apply {
- additionalQueryParams.removeAll(key)
- }
+ fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) }
fun removeAllAdditionalQueryParams(keys: Set) = apply {
- keys.forEach(::removeAdditionalQueryParams)
+ additionalQueryParams.removeAll(keys)
}
fun build(): AgenciesWithCoverageListParams =
- AgenciesWithCoverageListParams(
- additionalHeaders
- .asMap()
- .mapValues { it.value.toList().toImmutable() }
- .toImmutable(),
- additionalQueryParams
- .asMap()
- .mapValues { it.value.toList().toImmutable() }
- .toImmutable()
- )
+ AgenciesWithCoverageListParams(additionalHeaders.build(), additionalQueryParams.build())
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return /* spotless:off */ other is AgenciesWithCoverageListParams && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
}
+
+ override fun hashCode(): Int = /* spotless:off */ Objects.hash(additionalHeaders, additionalQueryParams) /* spotless:on */
+
+ override fun toString() =
+ "AgenciesWithCoverageListParams{additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListResponse.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListResponse.kt
index 0349ee9..b2224d0 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListResponse.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgenciesWithCoverageListResponse.kt
@@ -4,30 +4,34 @@ package org.onebusaway.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.fasterxml.jackson.databind.annotation.JsonDeserialize
import java.util.Objects
import org.onebusaway.core.ExcludeMissing
import org.onebusaway.core.JsonField
import org.onebusaway.core.JsonMissing
import org.onebusaway.core.JsonValue
import org.onebusaway.core.NoAutoDetect
+import org.onebusaway.core.checkRequired
+import org.onebusaway.core.immutableEmptyMap
import org.onebusaway.core.toImmutable
-@JsonDeserialize(builder = AgenciesWithCoverageListResponse.Builder::class)
@NoAutoDetect
class AgenciesWithCoverageListResponse
+@JsonCreator
private constructor(
- private val code: JsonField,
- private val currentTime: JsonField,
- private val text: JsonField,
- private val version: JsonField,
- private val data: JsonField,
- private val additionalProperties: Map,
+ @JsonProperty("code") @ExcludeMissing private val code: JsonField = JsonMissing.of(),
+ @JsonProperty("currentTime")
+ @ExcludeMissing
+ private val currentTime: JsonField = JsonMissing.of(),
+ @JsonProperty("text") @ExcludeMissing private val text: JsonField = JsonMissing.of(),
+ @JsonProperty("version")
+ @ExcludeMissing
+ private val version: JsonField = JsonMissing.of(),
+ @JsonProperty("data") @ExcludeMissing private val data: JsonField = JsonMissing.of(),
+ @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(),
) {
- private var validated: Boolean = false
-
fun code(): Long = code.getRequired("code")
fun currentTime(): Long = currentTime.getRequired("currentTime")
@@ -38,37 +42,41 @@ private constructor(
fun data(): Data = data.getRequired("data")
- fun toResponseWrapper(): ResponseWrapper =
- ResponseWrapper.builder()
- .code(code)
- .currentTime(currentTime)
- .text(text)
- .version(version)
- .build()
+ @JsonProperty("code") @ExcludeMissing fun _code(): JsonField = code
- @JsonProperty("code") @ExcludeMissing fun _code() = code
+ @JsonProperty("currentTime") @ExcludeMissing fun _currentTime(): JsonField = currentTime
- @JsonProperty("currentTime") @ExcludeMissing fun _currentTime() = currentTime
+ @JsonProperty("text") @ExcludeMissing fun _text(): JsonField = text
- @JsonProperty("text") @ExcludeMissing fun _text() = text
+ @JsonProperty("version") @ExcludeMissing fun _version(): JsonField = version
- @JsonProperty("version") @ExcludeMissing fun _version() = version
-
- @JsonProperty("data") @ExcludeMissing fun _data() = data
+ @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data
@JsonAnyGetter
@ExcludeMissing
fun _additionalProperties(): Map = additionalProperties
+ fun toResponseWrapper(): ResponseWrapper =
+ ResponseWrapper.builder()
+ .code(code)
+ .currentTime(currentTime)
+ .text(text)
+ .version(version)
+ .build()
+
+ private var validated: Boolean = false
+
fun validate(): AgenciesWithCoverageListResponse = apply {
- if (!validated) {
- code()
- currentTime()
- text()
- version()
- data().validate()
- validated = true
+ if (validated) {
+ return@apply
}
+
+ code()
+ currentTime()
+ text()
+ version()
+ data().validate()
+ validated = true
}
fun toBuilder() = Builder().from(this)
@@ -78,116 +86,128 @@ private constructor(
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ /** A builder for [AgenciesWithCoverageListResponse]. */
+ class Builder internal constructor() {
- private var code: JsonField = JsonMissing.of()
- private var currentTime: JsonField = JsonMissing.of()
- private var text: JsonField = JsonMissing.of()
- private var version: JsonField = JsonMissing.of()
- private var data: JsonField = JsonMissing.of()
+ private var code: JsonField? = null
+ private var currentTime: JsonField? = null
+ private var text: JsonField? = null
+ private var version: JsonField? = null
+ private var data: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
@JvmSynthetic
internal fun from(agenciesWithCoverageListResponse: AgenciesWithCoverageListResponse) =
apply {
- this.code = agenciesWithCoverageListResponse.code
- this.currentTime = agenciesWithCoverageListResponse.currentTime
- this.text = agenciesWithCoverageListResponse.text
- this.version = agenciesWithCoverageListResponse.version
- this.data = agenciesWithCoverageListResponse.data
- additionalProperties(agenciesWithCoverageListResponse.additionalProperties)
+ code = agenciesWithCoverageListResponse.code
+ currentTime = agenciesWithCoverageListResponse.currentTime
+ text = agenciesWithCoverageListResponse.text
+ version = agenciesWithCoverageListResponse.version
+ data = agenciesWithCoverageListResponse.data
+ additionalProperties =
+ agenciesWithCoverageListResponse.additionalProperties.toMutableMap()
}
fun code(code: Long) = code(JsonField.of(code))
- @JsonProperty("code")
- @ExcludeMissing
fun code(code: JsonField) = apply { this.code = code }
fun currentTime(currentTime: Long) = currentTime(JsonField.of(currentTime))
- @JsonProperty("currentTime")
- @ExcludeMissing
fun currentTime(currentTime: JsonField) = apply { this.currentTime = currentTime }
fun text(text: String) = text(JsonField.of(text))
- @JsonProperty("text")
- @ExcludeMissing
fun text(text: JsonField) = apply { this.text = text }
fun version(version: Long) = version(JsonField.of(version))
- @JsonProperty("version")
- @ExcludeMissing
fun version(version: JsonField) = apply { this.version = version }
fun data(data: Data) = data(JsonField.of(data))
- @JsonProperty("data")
- @ExcludeMissing
fun data(data: JsonField) = apply { this.data = data }
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
- this.additionalProperties.putAll(additionalProperties)
+ putAllAdditionalProperties(additionalProperties)
}
- @JsonAnySetter
fun putAdditionalProperty(key: String, value: JsonValue) = apply {
- this.additionalProperties.put(key, value)
+ 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)
+ }
+
fun build(): AgenciesWithCoverageListResponse =
AgenciesWithCoverageListResponse(
- code,
- currentTime,
- text,
- version,
- data,
+ checkRequired("code", code),
+ checkRequired("currentTime", currentTime),
+ checkRequired("text", text),
+ checkRequired("version", version),
+ checkRequired("data", data),
additionalProperties.toImmutable(),
)
}
- @JsonDeserialize(builder = Data.Builder::class)
@NoAutoDetect
class Data
+ @JsonCreator
private constructor(
- private val limitExceeded: JsonField,
- private val list: JsonField>,
- private val references: JsonField,
- private val additionalProperties: Map,
+ @JsonProperty("limitExceeded")
+ @ExcludeMissing
+ private val limitExceeded: JsonField = JsonMissing.of(),
+ @JsonProperty("list")
+ @ExcludeMissing
+ private val list: JsonField> = JsonMissing.of(),
+ @JsonProperty("references")
+ @ExcludeMissing
+ private val references: JsonField = JsonMissing.of(),
+ @JsonAnySetter
+ private val additionalProperties: Map = immutableEmptyMap(),
) {
- private var validated: Boolean = false
-
fun limitExceeded(): Boolean = limitExceeded.getRequired("limitExceeded")
fun list(): kotlin.collections.List = list.getRequired("list")
fun references(): References = references.getRequired("references")
- @JsonProperty("limitExceeded") @ExcludeMissing fun _limitExceeded() = limitExceeded
+ @JsonProperty("limitExceeded")
+ @ExcludeMissing
+ fun _limitExceeded(): JsonField = limitExceeded
- @JsonProperty("list") @ExcludeMissing fun _list() = list
+ @JsonProperty("list")
+ @ExcludeMissing
+ fun _list(): JsonField> = list
- @JsonProperty("references") @ExcludeMissing fun _references() = references
+ @JsonProperty("references")
+ @ExcludeMissing
+ fun _references(): JsonField = references
@JsonAnyGetter
@ExcludeMissing
fun _additionalProperties(): Map = additionalProperties
+ private var validated: Boolean = false
+
fun validate(): Data = apply {
- if (!validated) {
- limitExceeded()
- list().forEach { it.validate() }
- references().validate()
- validated = true
+ if (validated) {
+ return@apply
}
+
+ limitExceeded()
+ list().forEach { it.validate() }
+ references().validate()
+ validated = true
}
fun toBuilder() = Builder().from(this)
@@ -197,80 +217,104 @@ private constructor(
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ /** A builder for [Data]. */
+ class Builder internal constructor() {
- private var limitExceeded: JsonField = JsonMissing.of()
- private var list: JsonField> = JsonMissing.of()
- private var references: JsonField = JsonMissing.of()
+ private var limitExceeded: JsonField? = null
+ private var list: JsonField>? = null
+ private var references: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
@JvmSynthetic
internal fun from(data: Data) = apply {
- this.limitExceeded = data.limitExceeded
- this.list = data.list
- this.references = data.references
- additionalProperties(data.additionalProperties)
+ limitExceeded = data.limitExceeded
+ list = data.list.map { it.toMutableList() }
+ references = data.references
+ additionalProperties = data.additionalProperties.toMutableMap()
}
fun limitExceeded(limitExceeded: Boolean) = limitExceeded(JsonField.of(limitExceeded))
- @JsonProperty("limitExceeded")
- @ExcludeMissing
fun limitExceeded(limitExceeded: JsonField) = apply {
this.limitExceeded = limitExceeded
}
fun list(list: kotlin.collections.List) = list(JsonField.of(list))
- @JsonProperty("list")
- @ExcludeMissing
- fun list(list: JsonField>) = apply { this.list = list }
+ fun list(list: JsonField>) = apply {
+ this.list = list.map { it.toMutableList() }
+ }
+
+ fun addList(list: List) = apply {
+ this.list =
+ (this.list ?: JsonField.of(mutableListOf())).apply {
+ asKnown()
+ .orElseThrow {
+ IllegalStateException(
+ "Field was set to non-list type: ${javaClass.simpleName}"
+ )
+ }
+ .add(list)
+ }
+ }
fun references(references: References) = references(JsonField.of(references))
- @JsonProperty("references")
- @ExcludeMissing
fun references(references: JsonField) = apply {
this.references = references
}
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
- this.additionalProperties.putAll(additionalProperties)
+ putAllAdditionalProperties(additionalProperties)
}
- @JsonAnySetter
fun putAdditionalProperty(key: String, value: JsonValue) = apply {
- this.additionalProperties.put(key, value)
+ 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)
+ }
+
fun build(): Data =
Data(
- limitExceeded,
- list.map { it.toImmutable() },
- references,
+ checkRequired("limitExceeded", limitExceeded),
+ checkRequired("list", list).map { it.toImmutable() },
+ checkRequired("references", references),
additionalProperties.toImmutable(),
)
}
- @JsonDeserialize(builder = List.Builder::class)
@NoAutoDetect
class List
+ @JsonCreator
private constructor(
- private val agencyId: JsonField,
- private val lat: JsonField,
- private val latSpan: JsonField,
- private val lon: JsonField,
- private val lonSpan: JsonField,
- private val additionalProperties: Map,
+ @JsonProperty("agencyId")
+ @ExcludeMissing
+ private val agencyId: JsonField = JsonMissing.of(),
+ @JsonProperty("lat")
+ @ExcludeMissing
+ private val lat: JsonField = JsonMissing.of(),
+ @JsonProperty("latSpan")
+ @ExcludeMissing
+ private val latSpan: JsonField = JsonMissing.of(),
+ @JsonProperty("lon")
+ @ExcludeMissing
+ private val lon: JsonField = JsonMissing.of(),
+ @JsonProperty("lonSpan")
+ @ExcludeMissing
+ private val lonSpan: JsonField = JsonMissing.of(),
+ @JsonAnySetter
+ private val additionalProperties: Map = immutableEmptyMap(),
) {
- private var validated: Boolean = false
-
fun agencyId(): String = agencyId.getRequired("agencyId")
fun lat(): Double = lat.getRequired("lat")
@@ -281,29 +325,33 @@ private constructor(
fun lonSpan(): Double = lonSpan.getRequired("lonSpan")
- @JsonProperty("agencyId") @ExcludeMissing fun _agencyId() = agencyId
+ @JsonProperty("agencyId") @ExcludeMissing fun _agencyId(): JsonField = agencyId
- @JsonProperty("lat") @ExcludeMissing fun _lat() = lat
+ @JsonProperty("lat") @ExcludeMissing fun _lat(): JsonField = lat
- @JsonProperty("latSpan") @ExcludeMissing fun _latSpan() = latSpan
+ @JsonProperty("latSpan") @ExcludeMissing fun _latSpan(): JsonField = latSpan
- @JsonProperty("lon") @ExcludeMissing fun _lon() = lon
+ @JsonProperty("lon") @ExcludeMissing fun _lon(): JsonField = lon
- @JsonProperty("lonSpan") @ExcludeMissing fun _lonSpan() = lonSpan
+ @JsonProperty("lonSpan") @ExcludeMissing fun _lonSpan(): JsonField = lonSpan
@JsonAnyGetter
@ExcludeMissing
fun _additionalProperties(): Map = additionalProperties
+ private var validated: Boolean = false
+
fun validate(): List = apply {
- if (!validated) {
- agencyId()
- lat()
- latSpan()
- lon()
- lonSpan()
- validated = true
+ if (validated) {
+ return@apply
}
+
+ agencyId()
+ lat()
+ latSpan()
+ lon()
+ lonSpan()
+ validated = true
}
fun toBuilder() = Builder().from(this)
@@ -313,63 +361,53 @@ private constructor(
@JvmStatic fun builder() = Builder()
}
- class Builder {
+ /** A builder for [List]. */
+ class Builder internal constructor() {
- private var agencyId: JsonField = JsonMissing.of()
- private var lat: JsonField = JsonMissing.of()
- private var latSpan: JsonField = JsonMissing.of()
- private var lon: JsonField = JsonMissing.of()
- private var lonSpan: JsonField = JsonMissing.of()
+ private var agencyId: JsonField? = null
+ private var lat: JsonField? = null
+ private var latSpan: JsonField? = null
+ private var lon: JsonField? = null
+ private var lonSpan: JsonField? = null
private var additionalProperties: MutableMap = mutableMapOf()
@JvmSynthetic
internal fun from(list: List) = apply {
- this.agencyId = list.agencyId
- this.lat = list.lat
- this.latSpan = list.latSpan
- this.lon = list.lon
- this.lonSpan = list.lonSpan
- additionalProperties(list.additionalProperties)
+ agencyId = list.agencyId
+ lat = list.lat
+ latSpan = list.latSpan
+ lon = list.lon
+ lonSpan = list.lonSpan
+ additionalProperties = list.additionalProperties.toMutableMap()
}
fun agencyId(agencyId: String) = agencyId(JsonField.of(agencyId))
- @JsonProperty("agencyId")
- @ExcludeMissing
fun agencyId(agencyId: JsonField) = apply { this.agencyId = agencyId }
fun lat(lat: Double) = lat(JsonField.of(lat))
- @JsonProperty("lat")
- @ExcludeMissing
fun lat(lat: JsonField) = apply { this.lat = lat }
fun latSpan(latSpan: Double) = latSpan(JsonField.of(latSpan))
- @JsonProperty("latSpan")
- @ExcludeMissing
fun latSpan(latSpan: JsonField) = apply { this.latSpan = latSpan }
fun lon(lon: Double) = lon(JsonField.of(lon))
- @JsonProperty("lon")
- @ExcludeMissing
fun lon(lon: JsonField) = apply { this.lon = lon }
fun lonSpan(lonSpan: Double) = lonSpan(JsonField.of(lonSpan))
- @JsonProperty("lonSpan")
- @ExcludeMissing
fun lonSpan(lonSpan: JsonField) = apply { this.lonSpan = lonSpan }
fun additionalProperties(additionalProperties: Map) = apply {
this.additionalProperties.clear()
- this.additionalProperties.putAll(additionalProperties)
+ putAllAdditionalProperties(additionalProperties)
}
- @JsonAnySetter
fun putAdditionalProperty(key: String, value: JsonValue) = apply {
- this.additionalProperties.put(key, value)
+ additionalProperties.put(key, value)
}
fun putAllAdditionalProperties(additionalProperties: Map) =
@@ -377,13 +415,21 @@ private constructor(
this.additionalProperties.putAll(additionalProperties)
}
+ fun removeAdditionalProperty(key: String) = apply {
+ additionalProperties.remove(key)
+ }
+
+ fun removeAllAdditionalProperties(keys: Set) = apply {
+ keys.forEach(::removeAdditionalProperty)
+ }
+
fun build(): List =
List(
- agencyId,
- lat,
- latSpan,
- lon,
- lonSpan,
+ checkRequired("agencyId", agencyId),
+ checkRequired("lat", lat),
+ checkRequired("latSpan", latSpan),
+ checkRequired("lon", lon),
+ checkRequired("lonSpan", lonSpan),
additionalProperties.toImmutable(),
)
}
@@ -393,17 +439,14 @@ private constructor(
return true
}
- return /* spotless:off */ other is List && this.agencyId == other.agencyId && this.lat == other.lat && this.latSpan == other.latSpan && this.lon == other.lon && this.lonSpan == other.lonSpan && this.additionalProperties == other.additionalProperties /* spotless:on */
+ return /* spotless:off */ other is List && agencyId == other.agencyId && lat == other.lat && latSpan == other.latSpan && lon == other.lon && lonSpan == other.lonSpan && additionalProperties == other.additionalProperties /* spotless:on */
}
- private var hashCode: Int = 0
+ /* spotless:off */
+ private val hashCode: Int by lazy { Objects.hash(agencyId, lat, latSpan, lon, lonSpan, additionalProperties) }
+ /* spotless:on */
- override fun hashCode(): Int {
- if (hashCode == 0) {
- hashCode = /* spotless:off */ Objects.hash(agencyId, lat, latSpan, lon, lonSpan, additionalProperties) /* spotless:on */
- }
- return hashCode
- }
+ override fun hashCode(): Int = hashCode
override fun toString() =
"List{agencyId=$agencyId, lat=$lat, latSpan=$latSpan, lon=$lon, lonSpan=$lonSpan, additionalProperties=$additionalProperties}"
@@ -414,17 +457,14 @@ private constructor(
return true
}
- return /* spotless:off */ other is Data && this.limitExceeded == other.limitExceeded && this.list == other.list && this.references == other.references && this.additionalProperties == other.additionalProperties /* spotless:on */
+ return /* spotless:off */ other is Data && limitExceeded == other.limitExceeded && list == other.list && references == other.references && additionalProperties == other.additionalProperties /* spotless:on */
}
- private var hashCode: Int = 0
+ /* spotless:off */
+ private val hashCode: Int by lazy { Objects.hash(limitExceeded, list, references, additionalProperties) }
+ /* spotless:on */
- override fun hashCode(): Int {
- if (hashCode == 0) {
- hashCode = /* spotless:off */ Objects.hash(limitExceeded, list, references, additionalProperties) /* spotless:on */
- }
- return hashCode
- }
+ override fun hashCode(): Int = hashCode
override fun toString() =
"Data{limitExceeded=$limitExceeded, list=$list, references=$references, additionalProperties=$additionalProperties}"
@@ -435,17 +475,14 @@ private constructor(
return true
}
- return /* spotless:off */ other is AgenciesWithCoverageListResponse && this.code == other.code && this.currentTime == other.currentTime && this.text == other.text && this.version == other.version && this.data == other.data && this.additionalProperties == other.additionalProperties /* spotless:on */
+ return /* spotless:off */ other is AgenciesWithCoverageListResponse && code == other.code && currentTime == other.currentTime && text == other.text && version == other.version && data == other.data && additionalProperties == other.additionalProperties /* spotless:on */
}
- private var hashCode: Int = 0
+ /* spotless:off */
+ private val hashCode: Int by lazy { Objects.hash(code, currentTime, text, version, data, additionalProperties) }
+ /* spotless:on */
- override fun hashCode(): Int {
- if (hashCode == 0) {
- hashCode = /* spotless:off */ Objects.hash(code, currentTime, text, version, data, additionalProperties) /* spotless:on */
- }
- return hashCode
- }
+ override fun hashCode(): Int = hashCode
override fun toString() =
"AgenciesWithCoverageListResponse{code=$code, currentTime=$currentTime, text=$text, version=$version, data=$data, additionalProperties=$additionalProperties}"
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveParams.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveParams.kt
index 69a140e..3dbe375 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveParams.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveParams.kt
@@ -2,25 +2,30 @@
package org.onebusaway.models
-import com.google.common.collect.ArrayListMultimap
-import com.google.common.collect.ListMultimap
import java.util.Objects
import org.onebusaway.core.NoAutoDetect
-import org.onebusaway.core.toImmutable
-import org.onebusaway.models.*
+import org.onebusaway.core.Params
+import org.onebusaway.core.checkRequired
+import org.onebusaway.core.http.Headers
+import org.onebusaway.core.http.QueryParams
+/** Retrieve information for a specific transit agency identified by its unique ID. */
class AgencyRetrieveParams
-constructor(
+private constructor(
private val agencyId: String,
- private val additionalHeaders: Map>,
- private val additionalQueryParams: Map>,
-) {
+ private val additionalHeaders: Headers,
+ private val additionalQueryParams: QueryParams,
+) : Params {
fun agencyId(): String = agencyId
- @JvmSynthetic internal fun getHeaders(): Map> = additionalHeaders
+ fun _additionalHeaders(): Headers = additionalHeaders
- @JvmSynthetic internal fun getQueryParams(): Map> = additionalQueryParams
+ fun _additionalQueryParams(): QueryParams = additionalQueryParams
+
+ override fun _headers(): Headers = additionalHeaders
+
+ override fun _queryParams(): QueryParams = additionalQueryParams
fun getPathParam(index: Int): String {
return when (index) {
@@ -29,25 +34,6 @@ constructor(
}
}
- fun _additionalHeaders(): Map> = additionalHeaders
-
- fun _additionalQueryParams(): Map> = additionalQueryParams
-
- override fun equals(other: Any?): Boolean {
- if (this === other) {
- return true
- }
-
- return /* spotless:off */ other is AgencyRetrieveParams && this.agencyId == other.agencyId && this.additionalHeaders == other.additionalHeaders && this.additionalQueryParams == other.additionalQueryParams /* spotless:on */
- }
-
- override fun hashCode(): Int {
- return /* spotless:off */ Objects.hash(agencyId, additionalHeaders, additionalQueryParams) /* spotless:on */
- }
-
- override fun toString() =
- "AgencyRetrieveParams{agencyId=$agencyId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
-
fun toBuilder() = Builder().from(this)
companion object {
@@ -55,22 +41,28 @@ constructor(
@JvmStatic fun builder() = Builder()
}
+ /** A builder for [AgencyRetrieveParams]. */
@NoAutoDetect
- class Builder {
+ class Builder internal constructor() {
private var agencyId: String? = null
- private var additionalHeaders: ListMultimap = ArrayListMultimap.create()
- private var additionalQueryParams: ListMultimap = ArrayListMultimap.create()
+ private var additionalHeaders: Headers.Builder = Headers.builder()
+ private var additionalQueryParams: QueryParams.Builder = QueryParams.builder()
@JvmSynthetic
internal fun from(agencyRetrieveParams: AgencyRetrieveParams) = apply {
- this.agencyId = agencyRetrieveParams.agencyId
- additionalHeaders(agencyRetrieveParams.additionalHeaders)
- additionalQueryParams(agencyRetrieveParams.additionalQueryParams)
+ agencyId = agencyRetrieveParams.agencyId
+ additionalHeaders = agencyRetrieveParams.additionalHeaders.toBuilder()
+ additionalQueryParams = agencyRetrieveParams.additionalQueryParams.toBuilder()
}
fun agencyId(agencyId: String) = apply { this.agencyId = agencyId }
+ fun additionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.clear()
+ putAllAdditionalHeaders(additionalHeaders)
+ }
+
fun additionalHeaders(additionalHeaders: Map>) = apply {
this.additionalHeaders.clear()
putAllAdditionalHeaders(additionalHeaders)
@@ -81,29 +73,42 @@ constructor(
}
fun putAdditionalHeaders(name: String, values: Iterable) = apply {
- additionalHeaders.putAll(name, values)
+ additionalHeaders.put(name, values)
+ }
+
+ fun putAllAdditionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.putAll(additionalHeaders)
}
fun putAllAdditionalHeaders(additionalHeaders: Map>) = apply {
- additionalHeaders.forEach(::putAdditionalHeaders)
+ this.additionalHeaders.putAll(additionalHeaders)
}
fun replaceAdditionalHeaders(name: String, value: String) = apply {
- additionalHeaders.replaceValues(name, listOf(value))
+ additionalHeaders.replace(name, value)
}
fun replaceAdditionalHeaders(name: String, values: Iterable) = apply {
- additionalHeaders.replaceValues(name, values)
+ additionalHeaders.replace(name, values)
+ }
+
+ fun replaceAllAdditionalHeaders(additionalHeaders: Headers) = apply {
+ this.additionalHeaders.replaceAll(additionalHeaders)
}
fun replaceAllAdditionalHeaders(additionalHeaders: Map>) = apply {
- additionalHeaders.forEach(::replaceAdditionalHeaders)
+ this.additionalHeaders.replaceAll(additionalHeaders)
}
- fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.removeAll(name) }
+ fun removeAdditionalHeaders(name: String) = apply { additionalHeaders.remove(name) }
fun removeAllAdditionalHeaders(names: Set) = apply {
- names.forEach(::removeAdditionalHeaders)
+ additionalHeaders.removeAll(names)
+ }
+
+ fun additionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.clear()
+ putAllAdditionalQueryParams(additionalQueryParams)
}
fun additionalQueryParams(additionalQueryParams: Map>) = apply {
@@ -116,46 +121,59 @@ constructor(
}
fun putAdditionalQueryParams(key: String, values: Iterable) = apply {
- additionalQueryParams.putAll(key, values)
+ additionalQueryParams.put(key, values)
+ }
+
+ fun putAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.putAll(additionalQueryParams)
}
fun putAllAdditionalQueryParams(additionalQueryParams: Map>) =
apply {
- additionalQueryParams.forEach(::putAdditionalQueryParams)
+ this.additionalQueryParams.putAll(additionalQueryParams)
}
fun replaceAdditionalQueryParams(key: String, value: String) = apply {
- additionalQueryParams.replaceValues(key, listOf(value))
+ additionalQueryParams.replace(key, value)
}
fun replaceAdditionalQueryParams(key: String, values: Iterable) = apply {
- additionalQueryParams.replaceValues(key, values)
+ additionalQueryParams.replace(key, values)
+ }
+
+ fun replaceAllAdditionalQueryParams(additionalQueryParams: QueryParams) = apply {
+ this.additionalQueryParams.replaceAll(additionalQueryParams)
}
fun replaceAllAdditionalQueryParams(additionalQueryParams: Map>) =
apply {
- additionalQueryParams.forEach(::replaceAdditionalQueryParams)
+ this.additionalQueryParams.replaceAll(additionalQueryParams)
}
- fun removeAdditionalQueryParams(key: String) = apply {
- additionalQueryParams.removeAll(key)
- }
+ fun removeAdditionalQueryParams(key: String) = apply { additionalQueryParams.remove(key) }
fun removeAllAdditionalQueryParams(keys: Set) = apply {
- keys.forEach(::removeAdditionalQueryParams)
+ additionalQueryParams.removeAll(keys)
}
fun build(): AgencyRetrieveParams =
AgencyRetrieveParams(
- checkNotNull(agencyId) { "`agencyId` is required but was not set" },
- additionalHeaders
- .asMap()
- .mapValues { it.value.toList().toImmutable() }
- .toImmutable(),
- additionalQueryParams
- .asMap()
- .mapValues { it.value.toList().toImmutable() }
- .toImmutable(),
+ checkRequired("agencyId", agencyId),
+ additionalHeaders.build(),
+ additionalQueryParams.build(),
)
}
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) {
+ return true
+ }
+
+ return /* spotless:off */ other is AgencyRetrieveParams && agencyId == other.agencyId && additionalHeaders == other.additionalHeaders && additionalQueryParams == other.additionalQueryParams /* spotless:on */
+ }
+
+ override fun hashCode(): Int = /* spotless:off */ Objects.hash(agencyId, additionalHeaders, additionalQueryParams) /* spotless:on */
+
+ override fun toString() =
+ "AgencyRetrieveParams{agencyId=$agencyId, additionalHeaders=$additionalHeaders, additionalQueryParams=$additionalQueryParams}"
}
diff --git a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveResponse.kt b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveResponse.kt
index 3dbad5f..15b8791 100644
--- a/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveResponse.kt
+++ b/onebusaway-sdk-java-core/src/main/kotlin/org/onebusaway/models/AgencyRetrieveResponse.kt
@@ -4,8 +4,8 @@ package org.onebusaway.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.fasterxml.jackson.databind.annotation.JsonDeserialize
import java.util.Objects
import java.util.Optional
import org.onebusaway.core.ExcludeMissing
@@ -13,22 +13,26 @@ import org.onebusaway.core.JsonField
import org.onebusaway.core.JsonMissing
import org.onebusaway.core.JsonValue
import org.onebusaway.core.NoAutoDetect
+import org.onebusaway.core.checkRequired
+import org.onebusaway.core.immutableEmptyMap
import org.onebusaway.core.toImmutable
-@JsonDeserialize(builder = AgencyRetrieveResponse.Builder::class)
@NoAutoDetect
class AgencyRetrieveResponse
+@JsonCreator
private constructor(
- private val code: JsonField,
- private val currentTime: JsonField,
- private val text: JsonField