diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c7159c1..28e831b 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.0.2" + ".": "0.0.3" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 0caf7fc..92721c7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 5 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-b7fdba3d3f97c7debc22c7ca30b828bce81bcd64648df8c94029b27a3321ebb9.yml openapi_spec_hash: 03f1315f1d32ada42445ca920f047dff -config_hash: 0e1291f316b20497ad29b59a231a8680 +config_hash: cb5d75abef6264b5d86448caf7295afa diff --git a/CHANGELOG.md b/CHANGELOG.md index 8db43c8..3e1e157 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## 0.0.3 (2025-08-22) + +Full Changelog: [v0.0.2...v0.0.3](https://github.com/CASParser/cas-parser-java/compare/v0.0.2...v0.0.3) + +### Chores + +* **ci:** reduce log noise ([b66b3f9](https://github.com/CASParser/cas-parser-java/commit/b66b3f9da67d09730f90fc863a3aa05bd54d1b14)) +* **client:** refactor closing / shutdown ([a96f2f2](https://github.com/CASParser/cas-parser-java/commit/a96f2f22d6b5e36631fd79ad19e71b45c33a1402)) +* **internal:** fix multipart tests ([c564310](https://github.com/CASParser/cas-parser-java/commit/c56431084f5366b0b5887619ca0e1e4c44fe6e6c)) +* **internal:** support running formatters directly ([aec2ce4](https://github.com/CASParser/cas-parser-java/commit/aec2ce4f099cfebef00d9357a1c1cc8280caa83b)) + ## 0.0.2 (2025-08-18) Full Changelog: [v0.0.1...v0.0.2](https://github.com/CASParser/cas-parser-java/compare/v0.0.1...v0.0.2) diff --git a/README.md b/README.md index 7646bdb..0a2616d 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.0.2) -[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.0.2/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.2) +[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.0.3) +[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.0.3/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.3) @@ -13,7 +13,7 @@ It is generated with [Stainless](https://www.stainless.com/). -The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.2). +The REST API documentation can be found on [docs.casparser.in](https://docs.casparser.in/reference). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.0.3). @@ -24,7 +24,7 @@ The REST API documentation can be found on [docs.casparser.in](https://docs.casp ### Gradle ```kotlin -implementation("com.cas_parser.api:cas-parser-java:0.0.2") +implementation("com.cas_parser.api:cas-parser-java:0.0.3") ``` ### Maven @@ -33,7 +33,7 @@ implementation("com.cas_parser.api:cas-parser-java:0.0.2") com.cas_parser.api cas-parser-java - 0.0.2 + 0.0.3 ``` diff --git a/build.gradle.kts b/build.gradle.kts index 48085d5..45a77c9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ repositories { allprojects { group = "com.cas_parser.api" - version = "0.0.2" // x-release-please-version + version = "0.0.3" // x-release-please-version } subprojects { diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt index 2301ccd..d8b0b67 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientAsyncImpl.kt @@ -46,7 +46,7 @@ class CasParserClientAsyncImpl(private val clientOptions: ClientOptions) : CasPa override fun casGenerator(): CasGeneratorServiceAsync = casGenerator - override fun close() = clientOptions.httpClient.close() + override fun close() = clientOptions.close() class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : CasParserClientAsync.WithRawResponse { diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt index 0104e8f..fe0f962 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/client/CasParserClientImpl.kt @@ -46,7 +46,7 @@ class CasParserClientImpl(private val clientOptions: ClientOptions) : CasParserC override fun casGenerator(): CasGeneratorService = casGenerator - override fun close() = clientOptions.httpClient.close() + override fun close() = clientOptions.close() class WithRawResponseImpl internal constructor(private val clientOptions: ClientOptions) : CasParserClient.WithRawResponse { diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt index 516a36d..d330bc7 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/ClientOptions.kt @@ -21,6 +21,8 @@ private constructor( * The HTTP client to use in the SDK. * * Use the one published in `cas-parser-java-client-okhttp` or implement your own. + * + * This class takes ownership of the client and closes it when closed. */ @get:JvmName("httpClient") val httpClient: HttpClient, /** @@ -157,6 +159,8 @@ private constructor( * The HTTP client to use in the SDK. * * Use the one published in `cas-parser-java-client-okhttp` or implement your own. + * + * This class takes ownership of the client and closes it when closed. */ fun httpClient(httpClient: HttpClient) = apply { this.httpClient = PhantomReachableClosingHttpClient(httpClient) @@ -404,4 +408,18 @@ private constructor( ) } } + + /** + * Closes these client options, relinquishing any underlying resources. + * + * This is purposefully not inherited from [AutoCloseable] because the client options are + * long-lived and usually should not be synchronously closed via try-with-resources. + * + * It's also usually not necessary to call this method at all. the default client automatically + * releases threads and connections if they remain idle, but if you are writing an application + * that needs to aggressively release unused resources, then you may call this method. + */ + fun close() { + httpClient.close() + } } diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableExecutorService.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableExecutorService.kt new file mode 100644 index 0000000..d26c7ba --- /dev/null +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/core/PhantomReachableExecutorService.kt @@ -0,0 +1,58 @@ +package com.cas_parser.api.core + +import java.util.concurrent.Callable +import java.util.concurrent.ExecutorService +import java.util.concurrent.Future +import java.util.concurrent.TimeUnit + +/** + * A delegating wrapper around an [ExecutorService] that shuts it down once it's only phantom + * reachable. + * + * This class ensures the [ExecutorService] is shut down even if the user forgets to do it. + */ +internal class PhantomReachableExecutorService(private val executorService: ExecutorService) : + ExecutorService { + init { + closeWhenPhantomReachable(this) { executorService.shutdown() } + } + + override fun execute(command: Runnable) = executorService.execute(command) + + override fun shutdown() = executorService.shutdown() + + override fun shutdownNow(): MutableList = executorService.shutdownNow() + + override fun isShutdown(): Boolean = executorService.isShutdown + + override fun isTerminated(): Boolean = executorService.isTerminated + + override fun awaitTermination(timeout: Long, unit: TimeUnit): Boolean = + executorService.awaitTermination(timeout, unit) + + override fun submit(task: Callable): Future = executorService.submit(task) + + override fun submit(task: Runnable, result: T): Future = + executorService.submit(task, result) + + override fun submit(task: Runnable): Future<*> = executorService.submit(task) + + override fun invokeAll( + tasks: MutableCollection> + ): MutableList> = executorService.invokeAll(tasks) + + override fun invokeAll( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): MutableList> = executorService.invokeAll(tasks, timeout, unit) + + override fun invokeAny(tasks: MutableCollection>): T = + executorService.invokeAny(tasks) + + override fun invokeAny( + tasks: MutableCollection>, + timeout: Long, + unit: TimeUnit, + ): T = executorService.invokeAny(tasks, timeout, unit) +} diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt index e85c9de..7fd81ef 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCamsKfintechParamsTest.kt @@ -55,18 +55,6 @@ internal class CasParserCamsKfintechParamsTest { val body = params._body() - assertThat(body.filterValues { !it.value.isNull() }) - .usingRecursiveComparison() - // TODO(AssertJ): Replace this and the `mapValues` below with: - // https://github.com/assertj/assertj/issues/3165 - .withEqualsForType( - { a, b -> a.readBytes() contentEquals b.readBytes() }, - InputStream::class.java, - ) - .isEqualTo( - mapOf().mapValues { (_, field) -> - field.map { (it as? ByteArray)?.inputStream() ?: it } - } - ) + assertThat(body.filterValues { !it.value.isNull() }).isEmpty() } } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt index 778a492..6293280 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserCdslParamsTest.kt @@ -55,18 +55,6 @@ internal class CasParserCdslParamsTest { val body = params._body() - assertThat(body.filterValues { !it.value.isNull() }) - .usingRecursiveComparison() - // TODO(AssertJ): Replace this and the `mapValues` below with: - // https://github.com/assertj/assertj/issues/3165 - .withEqualsForType( - { a, b -> a.readBytes() contentEquals b.readBytes() }, - InputStream::class.java, - ) - .isEqualTo( - mapOf().mapValues { (_, field) -> - field.map { (it as? ByteArray)?.inputStream() ?: it } - } - ) + assertThat(body.filterValues { !it.value.isNull() }).isEmpty() } } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt index c593b64..fba23f6 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserNsdlParamsTest.kt @@ -55,18 +55,6 @@ internal class CasParserNsdlParamsTest { val body = params._body() - assertThat(body.filterValues { !it.value.isNull() }) - .usingRecursiveComparison() - // TODO(AssertJ): Replace this and the `mapValues` below with: - // https://github.com/assertj/assertj/issues/3165 - .withEqualsForType( - { a, b -> a.readBytes() contentEquals b.readBytes() }, - InputStream::class.java, - ) - .isEqualTo( - mapOf().mapValues { (_, field) -> - field.map { (it as? ByteArray)?.inputStream() ?: it } - } - ) + assertThat(body.filterValues { !it.value.isNull() }).isEmpty() } } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt index f3795e8..795fbfd 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/casparser/CasParserSmartParseParamsTest.kt @@ -55,18 +55,6 @@ internal class CasParserSmartParseParamsTest { val body = params._body() - assertThat(body.filterValues { !it.value.isNull() }) - .usingRecursiveComparison() - // TODO(AssertJ): Replace this and the `mapValues` below with: - // https://github.com/assertj/assertj/issues/3165 - .withEqualsForType( - { a, b -> a.readBytes() contentEquals b.readBytes() }, - InputStream::class.java, - ) - .isEqualTo( - mapOf().mapValues { (_, field) -> - field.map { (it as? ByteArray)?.inputStream() ?: it } - } - ) + assertThat(body.filterValues { !it.value.isNull() }).isEmpty() } } diff --git a/cas-parser-java-proguard-test/build.gradle.kts b/cas-parser-java-proguard-test/build.gradle.kts index dc5f093..de62f9c 100644 --- a/cas-parser-java-proguard-test/build.gradle.kts +++ b/cas-parser-java-proguard-test/build.gradle.kts @@ -37,8 +37,6 @@ val proguardJar by tasks.registering(proguard.gradle.ProGuardTask::class) { outjars(proguardJarPath) printmapping("${layout.buildDirectory.get()}/proguard-mapping.txt") - dontwarn() - val javaHome = System.getProperty("java.home") if (System.getProperty("java.version").startsWith("1.")) { // Before Java 9, the runtime classes were packaged in a single jar file. diff --git a/cas-parser-java-proguard-test/test.pro b/cas-parser-java-proguard-test/test.pro index 7cc2e8a..fcbe936 100644 --- a/cas-parser-java-proguard-test/test.pro +++ b/cas-parser-java-proguard-test/test.pro @@ -5,4 +5,5 @@ -keep class org.junit.** { *; } # Many warnings don't apply for our testing purposes. +-dontnote -dontwarn \ No newline at end of file diff --git a/scripts/format b/scripts/format index 7c0be4d..65db176 100755 --- a/scripts/format +++ b/scripts/format @@ -4,5 +4,18 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running formatters" -./gradlew format +if command -v ktfmt &> /dev/null; then + echo "==> Running ktfmt" + ./scripts/kotlin-format +else + echo "==> Running gradlew formatKotlin" + ./gradlew formatKotlin +fi + +if command -v palantir-java-format &> /dev/null; then + echo "==> Running palantir-java-format" + ./scripts/java-format +else + echo "==> Running gradlew formatJava" + ./gradlew formatJava +fi diff --git a/scripts/java-format b/scripts/java-format new file mode 100755 index 0000000..ad5febc --- /dev/null +++ b/scripts/java-format @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +find . -name "*.java" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r palantir-java-format --palantir --replace "$@" diff --git a/scripts/kotlin-format b/scripts/kotlin-format new file mode 100755 index 0000000..3b8be9e --- /dev/null +++ b/scripts/kotlin-format @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "$0")/.." + +find . -name "*.kt" -not -path "./buildSrc/build/*" -print0 | xargs -0 -r ktfmt --kotlinlang-style "$@" diff --git a/scripts/lint b/scripts/lint index aea8af7..dbc8f77 100755 --- a/scripts/lint +++ b/scripts/lint @@ -5,4 +5,19 @@ set -e cd "$(dirname "$0")/.." echo "==> Running lints" -./gradlew lint + +if command -v ktfmt &> /dev/null; then + echo "==> Checking ktfmt" + ./scripts/kotlin-format --dry-run --set-exit-if-changed +else + echo "==> Running gradlew lintKotlin" + ./gradlew lintKotlin +fi + +if command -v palantir-java-format &> /dev/null; then + echo "==> Checking palantir-java-format" + ./scripts/java-format --dry-run --set-exit-if-changed +else + echo "==> Running gradlew lintJava" + ./gradlew lintJava +fi