diff --git a/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClient.kt b/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClient.kt index a568e6a..fd8d3e3 100644 --- a/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClient.kt +++ b/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClient.kt @@ -9,6 +9,7 @@ import io.autorender.core.ClientOptions import io.autorender.core.LogLevel import io.autorender.core.Sleeper import io.autorender.core.Timeout +import io.autorender.core.http.AsyncStreamResponse import io.autorender.core.http.Headers import io.autorender.core.http.HttpClient import io.autorender.core.http.ProxyAuthenticator @@ -18,6 +19,7 @@ import java.net.Proxy import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.Executor import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory @@ -201,6 +203,17 @@ class AutorenderOkHttpClient private constructor() { */ fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + clientOptions.streamHandlerExecutor(streamHandlerExecutor) + } + /** * The interface to use for delaying execution, like during retries. * diff --git a/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClientAsync.kt b/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClientAsync.kt index 4cf1dc7..d6e9633 100644 --- a/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClientAsync.kt +++ b/autorender-java-client-okhttp/src/main/kotlin/io/autorender/client/okhttp/AutorenderOkHttpClientAsync.kt @@ -9,6 +9,7 @@ import io.autorender.core.ClientOptions import io.autorender.core.LogLevel import io.autorender.core.Sleeper import io.autorender.core.Timeout +import io.autorender.core.http.AsyncStreamResponse import io.autorender.core.http.Headers import io.autorender.core.http.HttpClient import io.autorender.core.http.ProxyAuthenticator @@ -18,6 +19,7 @@ import java.net.Proxy import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.Executor import java.util.concurrent.ExecutorService import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLSocketFactory @@ -201,6 +203,17 @@ class AutorenderOkHttpClientAsync private constructor() { */ fun jsonMapper(jsonMapper: JsonMapper) = apply { clientOptions.jsonMapper(jsonMapper) } + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + clientOptions.streamHandlerExecutor(streamHandlerExecutor) + } + /** * The interface to use for delaying execution, like during retries. * diff --git a/autorender-java-core/src/main/kotlin/io/autorender/core/AutoPager.kt b/autorender-java-core/src/main/kotlin/io/autorender/core/AutoPager.kt new file mode 100644 index 0000000..5248040 --- /dev/null +++ b/autorender-java-core/src/main/kotlin/io/autorender/core/AutoPager.kt @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.core + +import java.util.stream.Stream +import java.util.stream.StreamSupport + +class AutoPager private constructor(private val firstPage: Page) : Iterable { + + companion object { + + fun from(firstPage: Page): AutoPager = AutoPager(firstPage) + } + + override fun iterator(): Iterator = + generateSequence(firstPage) { if (it.hasNextPage()) it.nextPage() else null } + .flatMap { it.items() } + .iterator() + + fun stream(): Stream = StreamSupport.stream(spliterator(), false) +} diff --git a/autorender-java-core/src/main/kotlin/io/autorender/core/AutoPagerAsync.kt b/autorender-java-core/src/main/kotlin/io/autorender/core/AutoPagerAsync.kt new file mode 100644 index 0000000..96dc1b5 --- /dev/null +++ b/autorender-java-core/src/main/kotlin/io/autorender/core/AutoPagerAsync.kt @@ -0,0 +1,88 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.core + +import io.autorender.core.http.AsyncStreamResponse +import java.util.Optional +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CompletionException +import java.util.concurrent.Executor +import java.util.concurrent.atomic.AtomicReference + +class AutoPagerAsync +private constructor(private val firstPage: PageAsync, private val defaultExecutor: Executor) : + AsyncStreamResponse { + + companion object { + + fun from(firstPage: PageAsync, defaultExecutor: Executor): AutoPagerAsync = + AutoPagerAsync(firstPage, defaultExecutor) + } + + private val onCompleteFuture = CompletableFuture() + private val state = AtomicReference(State.NEW) + + override fun subscribe(handler: AsyncStreamResponse.Handler): AsyncStreamResponse = + subscribe(handler, defaultExecutor) + + override fun subscribe( + handler: AsyncStreamResponse.Handler, + executor: Executor, + ): AsyncStreamResponse = apply { + // TODO(JDK): Use `compareAndExchange` once targeting JDK 9. + check(state.compareAndSet(State.NEW, State.SUBSCRIBED)) { + if (state.get() == State.SUBSCRIBED) "Cannot subscribe more than once" + else "Cannot subscribe after the response is closed" + } + + fun PageAsync.handle(): CompletableFuture { + if (state.get() == State.CLOSED) { + return CompletableFuture.completedFuture(null) + } + + items().forEach { handler.onNext(it) } + return if (hasNextPage()) nextPage().thenCompose { it.handle() } + else CompletableFuture.completedFuture(null) + } + + executor.execute { + firstPage.handle().whenComplete { _, error -> + val actualError = + if (error is CompletionException && error.cause != null) error.cause else error + try { + handler.onComplete(Optional.ofNullable(actualError)) + } finally { + try { + if (actualError == null) { + onCompleteFuture.complete(null) + } else { + onCompleteFuture.completeExceptionally(actualError) + } + } finally { + close() + } + } + } + } + } + + override fun onCompleteFuture(): CompletableFuture = onCompleteFuture + + override fun close() { + val previousState = state.getAndSet(State.CLOSED) + if (previousState == State.CLOSED) { + return + } + + // When the stream is closed, we should always consider it closed. If it closed due + // to an error, then we will have already completed the future earlier, and this + // will be a no-op. + onCompleteFuture.complete(null) + } +} + +private enum class State { + NEW, + SUBSCRIBED, + CLOSED, +} diff --git a/autorender-java-core/src/main/kotlin/io/autorender/core/ClientOptions.kt b/autorender-java-core/src/main/kotlin/io/autorender/core/ClientOptions.kt index 8ed4837..030a688 100644 --- a/autorender-java-core/src/main/kotlin/io/autorender/core/ClientOptions.kt +++ b/autorender-java-core/src/main/kotlin/io/autorender/core/ClientOptions.kt @@ -3,6 +3,7 @@ package io.autorender.core import com.fasterxml.jackson.databind.json.JsonMapper +import io.autorender.core.http.AsyncStreamResponse import io.autorender.core.http.Headers import io.autorender.core.http.HttpClient import io.autorender.core.http.LoggingHttpClient @@ -12,6 +13,11 @@ import io.autorender.core.http.RetryingHttpClient import java.time.Clock import java.time.Duration import java.util.Optional +import java.util.concurrent.Executor +import java.util.concurrent.ExecutorService +import java.util.concurrent.Executors +import java.util.concurrent.ThreadFactory +import java.util.concurrent.atomic.AtomicLong import kotlin.jvm.optionals.getOrNull /** A class representing the SDK client configuration. */ @@ -41,6 +47,14 @@ private constructor( * needs to be overridden. */ @get:JvmName("jsonMapper") val jsonMapper: JsonMapper, + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + @get:JvmName("streamHandlerExecutor") val streamHandlerExecutor: Executor, /** * The interface to use for delaying execution, like during retries. * @@ -153,6 +167,7 @@ private constructor( private var httpClient: HttpClient? = null private var checkJacksonVersionCompatibility: Boolean = true private var jsonMapper: JsonMapper = jsonMapper() + private var streamHandlerExecutor: Executor? = null private var sleeper: Sleeper? = null private var clock: Clock = Clock.systemUTC() private var baseUrl: String? = null @@ -169,6 +184,7 @@ private constructor( httpClient = clientOptions.originalHttpClient checkJacksonVersionCompatibility = clientOptions.checkJacksonVersionCompatibility jsonMapper = clientOptions.jsonMapper + streamHandlerExecutor = clientOptions.streamHandlerExecutor sleeper = clientOptions.sleeper clock = clientOptions.clock baseUrl = clientOptions.baseUrl @@ -211,6 +227,20 @@ private constructor( */ fun jsonMapper(jsonMapper: JsonMapper) = apply { this.jsonMapper = jsonMapper } + /** + * The executor to use for running [AsyncStreamResponse.Handler] callbacks. + * + * Defaults to a dedicated cached thread pool. + * + * This class takes ownership of the executor and shuts it down, if possible, when closed. + */ + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + this.streamHandlerExecutor = + if (streamHandlerExecutor is ExecutorService) + PhantomReachableExecutorService(streamHandlerExecutor) + else streamHandlerExecutor + } + /** * The interface to use for delaying execution, like during retries. * @@ -427,6 +457,24 @@ private constructor( */ fun build(): ClientOptions { val httpClient = checkRequired("httpClient", httpClient) + val streamHandlerExecutor = + streamHandlerExecutor + ?: PhantomReachableExecutorService( + Executors.newCachedThreadPool( + object : ThreadFactory { + + private val threadFactory: ThreadFactory = + Executors.defaultThreadFactory() + private val count = AtomicLong(0) + + override fun newThread(runnable: Runnable): Thread = + threadFactory.newThread(runnable).also { + it.name = + "autorender-stream-handler-thread-${count.getAndIncrement()}" + } + } + ) + ) val sleeper = sleeper ?: PhantomReachableSleeper(DefaultSleeper()) val headers = Headers.builder() @@ -464,6 +512,7 @@ private constructor( .build(), checkJacksonVersionCompatibility, jsonMapper, + streamHandlerExecutor, sleeper, clock, baseUrl, @@ -490,6 +539,7 @@ private constructor( */ fun close() { httpClient.close() + (streamHandlerExecutor as? ExecutorService)?.shutdown() sleeper.close() } } diff --git a/autorender-java-core/src/main/kotlin/io/autorender/core/Page.kt b/autorender-java-core/src/main/kotlin/io/autorender/core/Page.kt new file mode 100644 index 0000000..d088d9d --- /dev/null +++ b/autorender-java-core/src/main/kotlin/io/autorender/core/Page.kt @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.core + +/** + * An interface representing a single page, with items of type [T], from a paginated endpoint + * response. + * + * Implementations of this interface are expected to request additional pages synchronously. For + * asynchronous pagination, see the [PageAsync] interface. + */ +interface Page { + + /** + * Returns whether there's another page after this one. + * + * The method generally doesn't make requests so the result depends entirely on the data in this + * page. If a significant amount of time has passed between requesting this page and calling + * this method, then the result could be stale. + */ + fun hasNextPage(): Boolean + + /** + * Returns the page after this one by making another request. + * + * @throws IllegalStateException if it's impossible to get the next page. This exception is + * avoidable by calling [hasNextPage] first. + */ + fun nextPage(): Page + + /** Returns the items in this page. */ + fun items(): List +} diff --git a/autorender-java-core/src/main/kotlin/io/autorender/core/PageAsync.kt b/autorender-java-core/src/main/kotlin/io/autorender/core/PageAsync.kt new file mode 100644 index 0000000..afe6214 --- /dev/null +++ b/autorender-java-core/src/main/kotlin/io/autorender/core/PageAsync.kt @@ -0,0 +1,35 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.core + +import java.util.concurrent.CompletableFuture + +/** + * An interface representing a single page, with items of type [T], from a paginated endpoint + * response. + * + * Implementations of this interface are expected to request additional pages asynchronously. For + * synchronous pagination, see the [Page] interface. + */ +interface PageAsync { + + /** + * Returns whether there's another page after this one. + * + * The method generally doesn't make requests so the result depends entirely on the data in this + * page. If a significant amount of time has passed between requesting this page and calling + * this method, then the result could be stale. + */ + fun hasNextPage(): Boolean + + /** + * Returns the page after this one by making another request. + * + * @throws IllegalStateException if it's impossible to get the next page. This exception is + * avoidable by calling [hasNextPage] first. + */ + fun nextPage(): CompletableFuture> + + /** Returns the items in this page. */ + fun items(): List +} diff --git a/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPage.kt b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPage.kt new file mode 100644 index 0000000..705e00d --- /dev/null +++ b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPage.kt @@ -0,0 +1,131 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.models.files + +import io.autorender.core.AutoPager +import io.autorender.core.Page +import io.autorender.core.checkRequired +import io.autorender.services.blocking.FileService +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrDefault +import kotlin.jvm.optionals.getOrNull + +/** @see FileService.list */ +class FileListPage +private constructor( + private val service: FileService, + private val params: FileListParams, + private val response: FileListPageResponse, +) : Page { + + /** + * Delegates to [FileListPageResponse], but gracefully handles missing data. + * + * @see FileListPageResponse.files + */ + fun files(): List = + response._files().getOptional("files").getOrNull() ?: emptyList() + + /** + * Delegates to [FileListPageResponse], but gracefully handles missing data. + * + * @see FileListPageResponse.meta + */ + fun meta(): Optional = response._meta().getOptional("meta") + + override fun items(): List = files() + + override fun hasNextPage(): Boolean = items().isNotEmpty() + + fun nextPageParams(): FileListParams { + val pageNumber = params.page().getOrDefault(1) + return params.toBuilder().page(pageNumber + 1).build() + } + + override fun nextPage(): FileListPage = service.list(nextPageParams()) + + fun autoPager(): AutoPager = AutoPager.from(this) + + /** The parameters that were used to request this page. */ + fun params(): FileListParams = params + + /** The response that this page was parsed from. */ + fun response(): FileListPageResponse = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [FileListPage]. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FileListPage]. */ + class Builder internal constructor() { + + private var service: FileService? = null + private var params: FileListParams? = null + private var response: FileListPageResponse? = null + + @JvmSynthetic + internal fun from(fileListPage: FileListPage) = apply { + service = fileListPage.service + params = fileListPage.params + response = fileListPage.response + } + + fun service(service: FileService) = apply { this.service = service } + + /** The parameters that were used to request this page. */ + fun params(params: FileListParams) = apply { this.params = params } + + /** The response that this page was parsed from. */ + fun response(response: FileListPageResponse) = apply { this.response = response } + + /** + * Returns an immutable instance of [FileListPage]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FileListPage = + FileListPage( + checkRequired("service", service), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FileListPage && + service == other.service && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, params, response) + + override fun toString() = "FileListPage{service=$service, params=$params, response=$response}" +} diff --git a/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPageAsync.kt b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPageAsync.kt new file mode 100644 index 0000000..323c27a --- /dev/null +++ b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPageAsync.kt @@ -0,0 +1,146 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.models.files + +import io.autorender.core.AutoPagerAsync +import io.autorender.core.PageAsync +import io.autorender.core.checkRequired +import io.autorender.services.async.FileServiceAsync +import java.util.Objects +import java.util.Optional +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import kotlin.jvm.optionals.getOrDefault +import kotlin.jvm.optionals.getOrNull + +/** @see FileServiceAsync.list */ +class FileListPageAsync +private constructor( + private val service: FileServiceAsync, + private val streamHandlerExecutor: Executor, + private val params: FileListParams, + private val response: FileListPageResponse, +) : PageAsync { + + /** + * Delegates to [FileListPageResponse], but gracefully handles missing data. + * + * @see FileListPageResponse.files + */ + fun files(): List = + response._files().getOptional("files").getOrNull() ?: emptyList() + + /** + * Delegates to [FileListPageResponse], but gracefully handles missing data. + * + * @see FileListPageResponse.meta + */ + fun meta(): Optional = response._meta().getOptional("meta") + + override fun items(): List = files() + + override fun hasNextPage(): Boolean = items().isNotEmpty() + + fun nextPageParams(): FileListParams { + val pageNumber = params.page().getOrDefault(1) + return params.toBuilder().page(pageNumber + 1).build() + } + + override fun nextPage(): CompletableFuture = service.list(nextPageParams()) + + fun autoPager(): AutoPagerAsync = + AutoPagerAsync.from(this, streamHandlerExecutor) + + /** The parameters that were used to request this page. */ + fun params(): FileListParams = params + + /** The response that this page was parsed from. */ + fun response(): FileListPageResponse = response + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [FileListPageAsync]. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FileListPageAsync]. */ + class Builder internal constructor() { + + private var service: FileServiceAsync? = null + private var streamHandlerExecutor: Executor? = null + private var params: FileListParams? = null + private var response: FileListPageResponse? = null + + @JvmSynthetic + internal fun from(fileListPageAsync: FileListPageAsync) = apply { + service = fileListPageAsync.service + streamHandlerExecutor = fileListPageAsync.streamHandlerExecutor + params = fileListPageAsync.params + response = fileListPageAsync.response + } + + fun service(service: FileServiceAsync) = apply { this.service = service } + + fun streamHandlerExecutor(streamHandlerExecutor: Executor) = apply { + this.streamHandlerExecutor = streamHandlerExecutor + } + + /** The parameters that were used to request this page. */ + fun params(params: FileListParams) = apply { this.params = params } + + /** The response that this page was parsed from. */ + fun response(response: FileListPageResponse) = apply { this.response = response } + + /** + * Returns an immutable instance of [FileListPageAsync]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .service() + * .streamHandlerExecutor() + * .params() + * .response() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FileListPageAsync = + FileListPageAsync( + checkRequired("service", service), + checkRequired("streamHandlerExecutor", streamHandlerExecutor), + checkRequired("params", params), + checkRequired("response", response), + ) + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FileListPageAsync && + service == other.service && + streamHandlerExecutor == other.streamHandlerExecutor && + params == other.params && + response == other.response + } + + override fun hashCode(): Int = Objects.hash(service, streamHandlerExecutor, params, response) + + override fun toString() = + "FileListPageAsync{service=$service, streamHandlerExecutor=$streamHandlerExecutor, params=$params, response=$response}" +} diff --git a/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPageResponse.kt b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPageResponse.kt new file mode 100644 index 0000000..2832165 --- /dev/null +++ b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListPageResponse.kt @@ -0,0 +1,537 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.models.files + +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 io.autorender.core.ExcludeMissing +import io.autorender.core.JsonField +import io.autorender.core.JsonMissing +import io.autorender.core.JsonValue +import io.autorender.core.checkKnown +import io.autorender.core.checkRequired +import io.autorender.core.toImmutable +import io.autorender.errors.AutorenderInvalidDataException +import java.util.Collections +import java.util.Objects +import kotlin.jvm.optionals.getOrNull + +/** Files list */ +class FileListPageResponse +@JsonCreator(mode = JsonCreator.Mode.DISABLED) +private constructor( + private val files: JsonField>, + private val meta: JsonField, + private val additionalProperties: MutableMap, +) { + + @JsonCreator + private constructor( + @JsonProperty("files") + @ExcludeMissing + files: JsonField> = JsonMissing.of(), + @JsonProperty("meta") @ExcludeMissing meta: JsonField = JsonMissing.of(), + ) : this(files, meta, mutableMapOf()) + + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun files(): List = files.getRequired("files") + + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun meta(): Meta = meta.getRequired("meta") + + /** + * Returns the raw JSON value of [files]. + * + * Unlike [files], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("files") @ExcludeMissing fun _files(): JsonField> = files + + /** + * Returns the raw JSON value of [meta]. + * + * Unlike [meta], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("meta") @ExcludeMissing fun _meta(): JsonField = meta + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [FileListPageResponse]. + * + * The following fields are required: + * ```java + * .files() + * .meta() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [FileListPageResponse]. */ + class Builder internal constructor() { + + private var files: JsonField>? = null + private var meta: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(fileListPageResponse: FileListPageResponse) = apply { + files = fileListPageResponse.files.map { it.toMutableList() } + meta = fileListPageResponse.meta + additionalProperties = fileListPageResponse.additionalProperties.toMutableMap() + } + + fun files(files: List) = files(JsonField.of(files)) + + /** + * Sets [Builder.files] to an arbitrary JSON value. + * + * You should usually call [Builder.files] with a well-typed `List` value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun files(files: JsonField>) = apply { + this.files = files.map { it.toMutableList() } + } + + /** + * Adds a single [FileListResponse] to [files]. + * + * @throws IllegalStateException if the field was previously set to a non-list. + */ + fun addFile(file: FileListResponse) = apply { + files = + (files ?: JsonField.of(mutableListOf())).also { checkKnown("files", it).add(file) } + } + + fun meta(meta: Meta) = meta(JsonField.of(meta)) + + /** + * Sets [Builder.meta] to an arbitrary JSON value. + * + * You should usually call [Builder.meta] with a well-typed [Meta] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun meta(meta: JsonField) = apply { this.meta = meta } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [FileListPageResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .files() + * .meta() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): FileListPageResponse = + FileListPageResponse( + checkRequired("files", files).map { it.toImmutable() }, + checkRequired("meta", meta), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws AutorenderInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): FileListPageResponse = apply { + if (validated) { + return@apply + } + + files().forEach { it.validate() } + meta().validate() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: AutorenderInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (files.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (meta.asKnown().getOrNull()?.validity() ?: 0) + + class Meta + @JsonCreator(mode = JsonCreator.Mode.DISABLED) + private constructor( + private val hasNext: JsonField, + private val hasPrev: JsonField, + private val limit: JsonField, + private val page: JsonField, + private val total: JsonField, + private val additionalProperties: MutableMap, + ) { + + @JsonCreator + private constructor( + @JsonProperty("hasNext") @ExcludeMissing hasNext: JsonField = JsonMissing.of(), + @JsonProperty("hasPrev") @ExcludeMissing hasPrev: JsonField = JsonMissing.of(), + @JsonProperty("limit") @ExcludeMissing limit: JsonField = JsonMissing.of(), + @JsonProperty("page") @ExcludeMissing page: JsonField = JsonMissing.of(), + @JsonProperty("total") @ExcludeMissing total: JsonField = JsonMissing.of(), + ) : this(hasNext, hasPrev, limit, page, total, mutableMapOf()) + + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun hasNext(): Boolean = hasNext.getRequired("hasNext") + + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun hasPrev(): Boolean = hasPrev.getRequired("hasPrev") + + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun limit(): Long = limit.getRequired("limit") + + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun page(): Long = page.getRequired("page") + + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun total(): Long = total.getRequired("total") + + /** + * Returns the raw JSON value of [hasNext]. + * + * Unlike [hasNext], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("hasNext") @ExcludeMissing fun _hasNext(): JsonField = hasNext + + /** + * Returns the raw JSON value of [hasPrev]. + * + * Unlike [hasPrev], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("hasPrev") @ExcludeMissing fun _hasPrev(): JsonField = hasPrev + + /** + * Returns the raw JSON value of [limit]. + * + * Unlike [limit], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("limit") @ExcludeMissing fun _limit(): JsonField = limit + + /** + * Returns the raw JSON value of [page]. + * + * Unlike [page], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("page") @ExcludeMissing fun _page(): JsonField = page + + /** + * Returns the raw JSON value of [total]. + * + * Unlike [total], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("total") @ExcludeMissing fun _total(): JsonField = total + + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } + + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) + + fun toBuilder() = Builder().from(this) + + companion object { + + /** + * Returns a mutable builder for constructing an instance of [Meta]. + * + * The following fields are required: + * ```java + * .hasNext() + * .hasPrev() + * .limit() + * .page() + * .total() + * ``` + */ + @JvmStatic fun builder() = Builder() + } + + /** A builder for [Meta]. */ + class Builder internal constructor() { + + private var hasNext: JsonField? = null + private var hasPrev: JsonField? = null + private var limit: JsonField? = null + private var page: JsonField? = null + private var total: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(meta: Meta) = apply { + hasNext = meta.hasNext + hasPrev = meta.hasPrev + limit = meta.limit + page = meta.page + total = meta.total + additionalProperties = meta.additionalProperties.toMutableMap() + } + + fun hasNext(hasNext: Boolean) = hasNext(JsonField.of(hasNext)) + + /** + * Sets [Builder.hasNext] to an arbitrary JSON value. + * + * You should usually call [Builder.hasNext] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun hasNext(hasNext: JsonField) = apply { this.hasNext = hasNext } + + fun hasPrev(hasPrev: Boolean) = hasPrev(JsonField.of(hasPrev)) + + /** + * Sets [Builder.hasPrev] to an arbitrary JSON value. + * + * You should usually call [Builder.hasPrev] with a well-typed [Boolean] value instead. + * This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun hasPrev(hasPrev: JsonField) = apply { this.hasPrev = hasPrev } + + fun limit(limit: Long) = limit(JsonField.of(limit)) + + /** + * Sets [Builder.limit] to an arbitrary JSON value. + * + * You should usually call [Builder.limit] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun limit(limit: JsonField) = apply { this.limit = limit } + + fun page(page: Long) = page(JsonField.of(page)) + + /** + * Sets [Builder.page] to an arbitrary JSON value. + * + * You should usually call [Builder.page] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun page(page: JsonField) = apply { this.page = page } + + fun total(total: Long) = total(JsonField.of(total)) + + /** + * Sets [Builder.total] to an arbitrary JSON value. + * + * You should usually call [Builder.total] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun total(total: JsonField) = apply { this.total = total } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } + + /** + * Returns an immutable instance of [Meta]. + * + * Further updates to this [Builder] will not mutate the returned instance. + * + * The following fields are required: + * ```java + * .hasNext() + * .hasPrev() + * .limit() + * .page() + * .total() + * ``` + * + * @throws IllegalStateException if any required field is unset. + */ + fun build(): Meta = + Meta( + checkRequired("hasNext", hasNext), + checkRequired("hasPrev", hasPrev), + checkRequired("limit", limit), + checkRequired("page", page), + checkRequired("total", total), + additionalProperties.toMutableMap(), + ) + } + + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types + * recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws AutorenderInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): Meta = apply { + if (validated) { + return@apply + } + + hasNext() + hasPrev() + limit() + page() + total() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: AutorenderInvalidDataException) { + false + } + + /** + * Returns a score indicating how many valid values are contained in this object + * recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (hasNext.asKnown().isPresent) 1 else 0) + + (if (hasPrev.asKnown().isPresent) 1 else 0) + + (if (limit.asKnown().isPresent) 1 else 0) + + (if (page.asKnown().isPresent) 1 else 0) + + (if (total.asKnown().isPresent) 1 else 0) + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is Meta && + hasNext == other.hasNext && + hasPrev == other.hasPrev && + limit == other.limit && + page == other.page && + total == other.total && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { + Objects.hash(hasNext, hasPrev, limit, page, total, additionalProperties) + } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "Meta{hasNext=$hasNext, hasPrev=$hasPrev, limit=$limit, page=$page, total=$total, additionalProperties=$additionalProperties}" + } + + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + + return other is FileListPageResponse && + files == other.files && + meta == other.meta && + additionalProperties == other.additionalProperties + } + + private val hashCode: Int by lazy { Objects.hash(files, meta, additionalProperties) } + + override fun hashCode(): Int = hashCode + + override fun toString() = + "FileListPageResponse{files=$files, meta=$meta, additionalProperties=$additionalProperties}" +} diff --git a/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListResponse.kt b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListResponse.kt index 5b86d2b..642c29e 100644 --- a/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListResponse.kt +++ b/autorender-java-core/src/main/kotlin/io/autorender/models/files/FileListResponse.kt @@ -20,1319 +20,773 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull -/** Files list */ class FileListResponse @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val files: JsonField>, - private val meta: JsonField, + private val id: JsonField, + private val createdAt: JsonField, + private val fileNo: JsonField, + private val folderName: JsonField, + private val folderNo: JsonField, + private val format: JsonField, + private val height: JsonField, + private val metadata: JsonField, + private val mimeType: JsonField, + private val name: JsonField, + private val path: JsonField, + private val size: JsonField, + private val source: JsonField, + private val tags: JsonField>, + private val updatedAt: JsonField, + private val url: JsonField, + private val width: JsonField, private val additionalProperties: MutableMap, ) { @JsonCreator private constructor( - @JsonProperty("files") @ExcludeMissing files: JsonField> = JsonMissing.of(), - @JsonProperty("meta") @ExcludeMissing meta: JsonField = JsonMissing.of(), - ) : this(files, meta, mutableMapOf()) + @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), + @JsonProperty("created_at") + @ExcludeMissing + createdAt: JsonField = JsonMissing.of(), + @JsonProperty("file_no") @ExcludeMissing fileNo: JsonField = JsonMissing.of(), + @JsonProperty("folder_name") + @ExcludeMissing + folderName: JsonField = JsonMissing.of(), + @JsonProperty("folder_no") @ExcludeMissing folderNo: JsonField = JsonMissing.of(), + @JsonProperty("format") @ExcludeMissing format: JsonField = JsonMissing.of(), + @JsonProperty("height") @ExcludeMissing height: JsonField = JsonMissing.of(), + @JsonProperty("metadata") @ExcludeMissing metadata: JsonField = JsonMissing.of(), + @JsonProperty("mime_type") @ExcludeMissing mimeType: JsonField = JsonMissing.of(), + @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), + @JsonProperty("path") @ExcludeMissing path: JsonField = JsonMissing.of(), + @JsonProperty("size") @ExcludeMissing size: JsonField = JsonMissing.of(), + @JsonProperty("source") @ExcludeMissing source: JsonField = JsonMissing.of(), + @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), + @JsonProperty("updated_at") + @ExcludeMissing + updatedAt: JsonField = JsonMissing.of(), + @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), + @JsonProperty("width") @ExcludeMissing width: JsonField = JsonMissing.of(), + ) : this( + id, + createdAt, + fileNo, + folderName, + folderNo, + format, + height, + metadata, + mimeType, + name, + path, + size, + source, + tags, + updatedAt, + url, + width, + mutableMapOf(), + ) /** * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ - fun files(): List = files.getRequired("files") + fun id(): String = id.getRequired("id") /** * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ - fun meta(): Meta = meta.getRequired("meta") + fun createdAt(): OffsetDateTime = createdAt.getRequired("created_at") /** - * Returns the raw JSON value of [files]. - * - * Unlike [files], this method doesn't throw if the JSON field has an unexpected type. + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). */ - @JsonProperty("files") @ExcludeMissing fun _files(): JsonField> = files + fun fileNo(): String = fileNo.getRequired("file_no") /** - * Returns the raw JSON value of [meta]. - * - * Unlike [meta], this method doesn't throw if the JSON field has an unexpected type. + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). */ - @JsonProperty("meta") @ExcludeMissing fun _meta(): JsonField = meta - - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } + fun folderName(): Optional = folderName.getOptional("folder_name") - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of [FileListResponse]. - * - * The following fields are required: - * ```java - * .files() - * .meta() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [FileListResponse]. */ - class Builder internal constructor() { - - private var files: JsonField>? = null - private var meta: JsonField? = null - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(fileListResponse: FileListResponse) = apply { - files = fileListResponse.files.map { it.toMutableList() } - meta = fileListResponse.meta - additionalProperties = fileListResponse.additionalProperties.toMutableMap() - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun folderNo(): Optional = folderNo.getOptional("folder_no") - fun files(files: List) = files(JsonField.of(files)) + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun format(): Optional = format.getOptional("format") - /** - * Sets [Builder.files] to an arbitrary JSON value. - * - * You should usually call [Builder.files] with a well-typed `List` value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun files(files: JsonField>) = apply { - this.files = files.map { it.toMutableList() } - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun height(): Optional = height.getOptional("height") - /** - * Adds a single [File] to [files]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addFile(file: File) = apply { - files = - (files ?: JsonField.of(mutableListOf())).also { checkKnown("files", it).add(file) } - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun metadata(): Optional = metadata.getOptional("metadata") - fun meta(meta: Meta) = meta(JsonField.of(meta)) + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun mimeType(): String = mimeType.getRequired("mime_type") - /** - * Sets [Builder.meta] to an arbitrary JSON value. - * - * You should usually call [Builder.meta] with a well-typed [Meta] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported value. - */ - fun meta(meta: JsonField) = apply { this.meta = meta } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun name(): String = name.getRequired("name") - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun path(): String = path.getRequired("path") - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun size(): Long = size.getRequired("size") - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun source(): String = source.getRequired("source") - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun tags(): List = tags.getRequired("tags") - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun updatedAt(): Optional = updatedAt.getOptional("updated_at") - /** - * Returns an immutable instance of [FileListResponse]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .files() - * .meta() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): FileListResponse = - FileListResponse( - checkRequired("files", files).map { it.toImmutable() }, - checkRequired("meta", meta), - additionalProperties.toMutableMap(), - ) - } + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is + * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + */ + fun url(): String = url.getRequired("url") - private var validated: Boolean = false + /** + * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun width(): Optional = width.getOptional("width") /** - * Validates that the types of all values in this object match their expected types recursively. + * Returns the raw JSON value of [id]. * - * This method is _not_ forwards compatible with new types from the API for existing fields. - * - * @throws AutorenderInvalidDataException if any value type in this object doesn't match its - * expected type. + * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. */ - fun validate(): FileListResponse = apply { - if (validated) { - return@apply - } - - files().forEach { it.validate() } - meta().validate() - validated = true - } - - fun isValid(): Boolean = - try { - validate() - true - } catch (e: AutorenderInvalidDataException) { - false - } + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id /** - * Returns a score indicating how many valid values are contained in this object recursively. + * Returns the raw JSON value of [createdAt]. * - * Used for best match union deserialization. + * Unlike [createdAt], this method doesn't throw if the JSON field has an unexpected type. */ - @JvmSynthetic - internal fun validity(): Int = - (files.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + - (meta.asKnown().getOrNull()?.validity() ?: 0) - - class File - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val id: JsonField, - private val createdAt: JsonField, - private val fileNo: JsonField, - private val folderName: JsonField, - private val folderNo: JsonField, - private val format: JsonField, - private val height: JsonField, - private val metadata: JsonField, - private val mimeType: JsonField, - private val name: JsonField, - private val path: JsonField, - private val size: JsonField, - private val source: JsonField, - private val tags: JsonField>, - private val updatedAt: JsonField, - private val url: JsonField, - private val width: JsonField, - private val additionalProperties: MutableMap, - ) { - - @JsonCreator - private constructor( - @JsonProperty("id") @ExcludeMissing id: JsonField = JsonMissing.of(), - @JsonProperty("created_at") - @ExcludeMissing - createdAt: JsonField = JsonMissing.of(), - @JsonProperty("file_no") @ExcludeMissing fileNo: JsonField = JsonMissing.of(), - @JsonProperty("folder_name") - @ExcludeMissing - folderName: JsonField = JsonMissing.of(), - @JsonProperty("folder_no") - @ExcludeMissing - folderNo: JsonField = JsonMissing.of(), - @JsonProperty("format") @ExcludeMissing format: JsonField = JsonMissing.of(), - @JsonProperty("height") @ExcludeMissing height: JsonField = JsonMissing.of(), - @JsonProperty("metadata") - @ExcludeMissing - metadata: JsonField = JsonMissing.of(), - @JsonProperty("mime_type") - @ExcludeMissing - mimeType: JsonField = JsonMissing.of(), - @JsonProperty("name") @ExcludeMissing name: JsonField = JsonMissing.of(), - @JsonProperty("path") @ExcludeMissing path: JsonField = JsonMissing.of(), - @JsonProperty("size") @ExcludeMissing size: JsonField = JsonMissing.of(), - @JsonProperty("source") @ExcludeMissing source: JsonField = JsonMissing.of(), - @JsonProperty("tags") @ExcludeMissing tags: JsonField> = JsonMissing.of(), - @JsonProperty("updated_at") - @ExcludeMissing - updatedAt: JsonField = JsonMissing.of(), - @JsonProperty("url") @ExcludeMissing url: JsonField = JsonMissing.of(), - @JsonProperty("width") @ExcludeMissing width: JsonField = JsonMissing.of(), - ) : this( - id, - createdAt, - fileNo, - folderName, - folderNo, - format, - height, - metadata, - mimeType, - name, - path, - size, - source, - tags, - updatedAt, - url, - width, - mutableMapOf(), - ) - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun id(): String = id.getRequired("id") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun createdAt(): OffsetDateTime = createdAt.getRequired("created_at") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun fileNo(): String = fileNo.getRequired("file_no") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun folderName(): Optional = folderName.getOptional("folder_name") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun folderNo(): Optional = folderNo.getOptional("folder_no") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun format(): Optional = format.getOptional("format") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun height(): Optional = height.getOptional("height") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun metadata(): Optional = metadata.getOptional("metadata") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun mimeType(): String = mimeType.getRequired("mime_type") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun name(): String = name.getRequired("name") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun path(): String = path.getRequired("path") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun size(): Long = size.getRequired("size") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun source(): String = source.getRequired("source") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun tags(): List = tags.getRequired("tags") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun updatedAt(): Optional = updatedAt.getOptional("updated_at") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun url(): String = url.getRequired("url") - - /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type (e.g. if - * the server responded with an unexpected value). - */ - fun width(): Optional = width.getOptional("width") - - /** - * Returns the raw JSON value of [id]. - * - * Unlike [id], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id - - /** - * Returns the raw JSON value of [createdAt]. - * - * Unlike [createdAt], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("created_at") - @ExcludeMissing - fun _createdAt(): JsonField = createdAt - - /** - * Returns the raw JSON value of [fileNo]. - * - * Unlike [fileNo], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("file_no") @ExcludeMissing fun _fileNo(): JsonField = fileNo - - /** - * Returns the raw JSON value of [folderName]. - * - * Unlike [folderName], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("folder_name") - @ExcludeMissing - fun _folderName(): JsonField = folderName - - /** - * Returns the raw JSON value of [folderNo]. - * - * Unlike [folderNo], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("folder_no") @ExcludeMissing fun _folderNo(): JsonField = folderNo - - /** - * Returns the raw JSON value of [format]. - * - * Unlike [format], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("format") @ExcludeMissing fun _format(): JsonField = format - - /** - * Returns the raw JSON value of [height]. - * - * Unlike [height], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("height") @ExcludeMissing fun _height(): JsonField = height - - /** - * Returns the raw JSON value of [metadata]. - * - * Unlike [metadata], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonField = metadata - - /** - * Returns the raw JSON value of [mimeType]. - * - * Unlike [mimeType], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("mime_type") @ExcludeMissing fun _mimeType(): JsonField = mimeType - - /** - * Returns the raw JSON value of [name]. - * - * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name - - /** - * Returns the raw JSON value of [path]. - * - * Unlike [path], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("path") @ExcludeMissing fun _path(): JsonField = path - - /** - * Returns the raw JSON value of [size]. - * - * Unlike [size], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("size") @ExcludeMissing fun _size(): JsonField = size - - /** - * Returns the raw JSON value of [source]. - * - * Unlike [source], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("source") @ExcludeMissing fun _source(): JsonField = source - - /** - * Returns the raw JSON value of [tags]. - * - * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags - - /** - * Returns the raw JSON value of [updatedAt]. - * - * Unlike [updatedAt], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("updated_at") - @ExcludeMissing - fun _updatedAt(): JsonField = updatedAt - - /** - * Returns the raw JSON value of [url]. - * - * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url - - /** - * Returns the raw JSON value of [width]. - * - * Unlike [width], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("width") @ExcludeMissing fun _width(): JsonField = width - - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) - } - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) - - fun toBuilder() = Builder().from(this) - - companion object { - - /** - * Returns a mutable builder for constructing an instance of [File]. - * - * The following fields are required: - * ```java - * .id() - * .createdAt() - * .fileNo() - * .folderName() - * .folderNo() - * .format() - * .height() - * .metadata() - * .mimeType() - * .name() - * .path() - * .size() - * .source() - * .tags() - * .updatedAt() - * .url() - * .width() - * ``` - */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [File]. */ - class Builder internal constructor() { - - private var id: JsonField? = null - private var createdAt: JsonField? = null - private var fileNo: JsonField? = null - private var folderName: JsonField? = null - private var folderNo: JsonField? = null - private var format: JsonField? = null - private var height: JsonField? = null - private var metadata: JsonField? = null - private var mimeType: JsonField? = null - private var name: JsonField? = null - private var path: JsonField? = null - private var size: JsonField? = null - private var source: JsonField? = null - private var tags: JsonField>? = null - private var updatedAt: JsonField? = null - private var url: JsonField? = null - private var width: JsonField? = null - private var additionalProperties: MutableMap = mutableMapOf() - - @JvmSynthetic - internal fun from(file: File) = apply { - id = file.id - createdAt = file.createdAt - fileNo = file.fileNo - folderName = file.folderName - folderNo = file.folderNo - format = file.format - height = file.height - metadata = file.metadata - mimeType = file.mimeType - name = file.name - path = file.path - size = file.size - source = file.source - tags = file.tags.map { it.toMutableList() } - updatedAt = file.updatedAt - url = file.url - width = file.width - additionalProperties = file.additionalProperties.toMutableMap() - } - - fun id(id: String) = id(JsonField.of(id)) - - /** - * Sets [Builder.id] to an arbitrary JSON value. - * - * You should usually call [Builder.id] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun id(id: JsonField) = apply { this.id = id } - - fun createdAt(createdAt: OffsetDateTime) = createdAt(JsonField.of(createdAt)) - - /** - * Sets [Builder.createdAt] to an arbitrary JSON value. - * - * You should usually call [Builder.createdAt] with a well-typed [OffsetDateTime] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun createdAt(createdAt: JsonField) = apply { - this.createdAt = createdAt - } - - fun fileNo(fileNo: String) = fileNo(JsonField.of(fileNo)) - - /** - * Sets [Builder.fileNo] to an arbitrary JSON value. - * - * You should usually call [Builder.fileNo] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun fileNo(fileNo: JsonField) = apply { this.fileNo = fileNo } - - fun folderName(folderName: String?) = folderName(JsonField.ofNullable(folderName)) - - /** Alias for calling [Builder.folderName] with `folderName.orElse(null)`. */ - fun folderName(folderName: Optional) = folderName(folderName.getOrNull()) - - /** - * Sets [Builder.folderName] to an arbitrary JSON value. - * - * You should usually call [Builder.folderName] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun folderName(folderName: JsonField) = apply { this.folderName = folderName } - - fun folderNo(folderNo: String?) = folderNo(JsonField.ofNullable(folderNo)) - - /** Alias for calling [Builder.folderNo] with `folderNo.orElse(null)`. */ - fun folderNo(folderNo: Optional) = folderNo(folderNo.getOrNull()) - - /** - * Sets [Builder.folderNo] to an arbitrary JSON value. - * - * You should usually call [Builder.folderNo] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun folderNo(folderNo: JsonField) = apply { this.folderNo = folderNo } - - fun format(format: String?) = format(JsonField.ofNullable(format)) - - /** Alias for calling [Builder.format] with `format.orElse(null)`. */ - fun format(format: Optional) = format(format.getOrNull()) - - /** - * Sets [Builder.format] to an arbitrary JSON value. - * - * You should usually call [Builder.format] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun format(format: JsonField) = apply { this.format = format } - - fun height(height: Long?) = height(JsonField.ofNullable(height)) - - /** - * Alias for [Builder.height]. - * - * This unboxed primitive overload exists for backwards compatibility. - */ - fun height(height: Long) = height(height as Long?) - - /** Alias for calling [Builder.height] with `height.orElse(null)`. */ - fun height(height: Optional) = height(height.getOrNull()) - - /** - * Sets [Builder.height] to an arbitrary JSON value. - * - * You should usually call [Builder.height] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun height(height: JsonField) = apply { this.height = height } - - fun metadata(metadata: Metadata?) = metadata(JsonField.ofNullable(metadata)) - - /** Alias for calling [Builder.metadata] with `metadata.orElse(null)`. */ - fun metadata(metadata: Optional) = metadata(metadata.getOrNull()) - - /** - * Sets [Builder.metadata] to an arbitrary JSON value. - * - * You should usually call [Builder.metadata] with a well-typed [Metadata] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun metadata(metadata: JsonField) = apply { this.metadata = metadata } - - fun mimeType(mimeType: String) = mimeType(JsonField.of(mimeType)) - - /** - * Sets [Builder.mimeType] to an arbitrary JSON value. - * - * You should usually call [Builder.mimeType] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun mimeType(mimeType: JsonField) = apply { this.mimeType = mimeType } - - fun name(name: String) = name(JsonField.of(name)) - - /** - * Sets [Builder.name] to an arbitrary JSON value. - * - * You should usually call [Builder.name] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun name(name: JsonField) = apply { this.name = name } - - fun path(path: String) = path(JsonField.of(path)) - - /** - * Sets [Builder.path] to an arbitrary JSON value. - * - * You should usually call [Builder.path] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun path(path: JsonField) = apply { this.path = path } - - fun size(size: Long) = size(JsonField.of(size)) - - /** - * Sets [Builder.size] to an arbitrary JSON value. - * - * You should usually call [Builder.size] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun size(size: JsonField) = apply { this.size = size } - - fun source(source: String) = source(JsonField.of(source)) - - /** - * Sets [Builder.source] to an arbitrary JSON value. - * - * You should usually call [Builder.source] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun source(source: JsonField) = apply { this.source = source } + @JsonProperty("created_at") + @ExcludeMissing + fun _createdAt(): JsonField = createdAt - fun tags(tags: List) = tags(JsonField.of(tags)) + /** + * Returns the raw JSON value of [fileNo]. + * + * Unlike [fileNo], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("file_no") @ExcludeMissing fun _fileNo(): JsonField = fileNo - /** - * Sets [Builder.tags] to an arbitrary JSON value. - * - * You should usually call [Builder.tags] with a well-typed `List` value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun tags(tags: JsonField>) = apply { - this.tags = tags.map { it.toMutableList() } - } + /** + * Returns the raw JSON value of [folderName]. + * + * Unlike [folderName], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("folder_name") @ExcludeMissing fun _folderName(): JsonField = folderName - /** - * Adds a single [String] to [tags]. - * - * @throws IllegalStateException if the field was previously set to a non-list. - */ - fun addTag(tag: String) = apply { - tags = - (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } - } + /** + * Returns the raw JSON value of [folderNo]. + * + * Unlike [folderNo], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("folder_no") @ExcludeMissing fun _folderNo(): JsonField = folderNo - fun updatedAt(updatedAt: OffsetDateTime?) = updatedAt(JsonField.ofNullable(updatedAt)) + /** + * Returns the raw JSON value of [format]. + * + * Unlike [format], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("format") @ExcludeMissing fun _format(): JsonField = format - /** Alias for calling [Builder.updatedAt] with `updatedAt.orElse(null)`. */ - fun updatedAt(updatedAt: Optional) = updatedAt(updatedAt.getOrNull()) + /** + * Returns the raw JSON value of [height]. + * + * Unlike [height], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("height") @ExcludeMissing fun _height(): JsonField = height - /** - * Sets [Builder.updatedAt] to an arbitrary JSON value. - * - * You should usually call [Builder.updatedAt] with a well-typed [OffsetDateTime] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun updatedAt(updatedAt: JsonField) = apply { - this.updatedAt = updatedAt - } + /** + * Returns the raw JSON value of [metadata]. + * + * Unlike [metadata], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonField = metadata - fun url(url: String) = url(JsonField.of(url)) + /** + * Returns the raw JSON value of [mimeType]. + * + * Unlike [mimeType], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("mime_type") @ExcludeMissing fun _mimeType(): JsonField = mimeType - /** - * Sets [Builder.url] to an arbitrary JSON value. - * - * You should usually call [Builder.url] with a well-typed [String] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun url(url: JsonField) = apply { this.url = url } + /** + * Returns the raw JSON value of [name]. + * + * Unlike [name], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name - fun width(width: Long?) = width(JsonField.ofNullable(width)) + /** + * Returns the raw JSON value of [path]. + * + * Unlike [path], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("path") @ExcludeMissing fun _path(): JsonField = path - /** - * Alias for [Builder.width]. - * - * This unboxed primitive overload exists for backwards compatibility. - */ - fun width(width: Long) = width(width as Long?) + /** + * Returns the raw JSON value of [size]. + * + * Unlike [size], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("size") @ExcludeMissing fun _size(): JsonField = size - /** Alias for calling [Builder.width] with `width.orElse(null)`. */ - fun width(width: Optional) = width(width.getOrNull()) + /** + * Returns the raw JSON value of [source]. + * + * Unlike [source], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("source") @ExcludeMissing fun _source(): JsonField = source - /** - * Sets [Builder.width] to an arbitrary JSON value. - * - * You should usually call [Builder.width] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun width(width: JsonField) = apply { this.width = width } + /** + * Returns the raw JSON value of [tags]. + * + * Unlike [tags], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("tags") @ExcludeMissing fun _tags(): JsonField> = tags - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + /** + * Returns the raw JSON value of [updatedAt]. + * + * Unlike [updatedAt], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("updated_at") + @ExcludeMissing + fun _updatedAt(): JsonField = updatedAt - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * Returns the raw JSON value of [url]. + * + * Unlike [url], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("url") @ExcludeMissing fun _url(): JsonField = url - fun putAllAdditionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.putAll(additionalProperties) - } + /** + * Returns the raw JSON value of [width]. + * + * Unlike [width], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("width") @ExcludeMissing fun _width(): JsonField = width - fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + @JsonAnySetter + private fun putAdditionalProperty(key: String, value: JsonValue) { + additionalProperties.put(key, value) + } - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + @JsonAnyGetter + @ExcludeMissing + fun _additionalProperties(): Map = + Collections.unmodifiableMap(additionalProperties) - /** - * Returns an immutable instance of [File]. - * - * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .id() - * .createdAt() - * .fileNo() - * .folderName() - * .folderNo() - * .format() - * .height() - * .metadata() - * .mimeType() - * .name() - * .path() - * .size() - * .source() - * .tags() - * .updatedAt() - * .url() - * .width() - * ``` - * - * @throws IllegalStateException if any required field is unset. - */ - fun build(): File = - File( - checkRequired("id", id), - checkRequired("createdAt", createdAt), - checkRequired("fileNo", fileNo), - checkRequired("folderName", folderName), - checkRequired("folderNo", folderNo), - checkRequired("format", format), - checkRequired("height", height), - checkRequired("metadata", metadata), - checkRequired("mimeType", mimeType), - checkRequired("name", name), - checkRequired("path", path), - checkRequired("size", size), - checkRequired("source", source), - checkRequired("tags", tags).map { it.toImmutable() }, - checkRequired("updatedAt", updatedAt), - checkRequired("url", url), - checkRequired("width", width), - additionalProperties.toMutableMap(), - ) - } + fun toBuilder() = Builder().from(this) - private var validated: Boolean = false + companion object { /** - * Validates that the types of all values in this object match their expected types - * recursively. - * - * This method is _not_ forwards compatible with new types from the API for existing fields. + * Returns a mutable builder for constructing an instance of [FileListResponse]. * - * @throws AutorenderInvalidDataException if any value type in this object doesn't match its - * expected type. + * The following fields are required: + * ```java + * .id() + * .createdAt() + * .fileNo() + * .folderName() + * .folderNo() + * .format() + * .height() + * .metadata() + * .mimeType() + * .name() + * .path() + * .size() + * .source() + * .tags() + * .updatedAt() + * .url() + * .width() + * ``` */ - fun validate(): File = apply { - if (validated) { - return@apply - } + @JvmStatic fun builder() = Builder() + } - id() - createdAt() - fileNo() - folderName() - folderNo() - format() - height() - metadata().ifPresent { it.validate() } - mimeType() - name() - path() - size() - source() - tags() - updatedAt() - url() - width() - validated = true + /** A builder for [FileListResponse]. */ + class Builder internal constructor() { + + private var id: JsonField? = null + private var createdAt: JsonField? = null + private var fileNo: JsonField? = null + private var folderName: JsonField? = null + private var folderNo: JsonField? = null + private var format: JsonField? = null + private var height: JsonField? = null + private var metadata: JsonField? = null + private var mimeType: JsonField? = null + private var name: JsonField? = null + private var path: JsonField? = null + private var size: JsonField? = null + private var source: JsonField? = null + private var tags: JsonField>? = null + private var updatedAt: JsonField? = null + private var url: JsonField? = null + private var width: JsonField? = null + private var additionalProperties: MutableMap = mutableMapOf() + + @JvmSynthetic + internal fun from(fileListResponse: FileListResponse) = apply { + id = fileListResponse.id + createdAt = fileListResponse.createdAt + fileNo = fileListResponse.fileNo + folderName = fileListResponse.folderName + folderNo = fileListResponse.folderNo + format = fileListResponse.format + height = fileListResponse.height + metadata = fileListResponse.metadata + mimeType = fileListResponse.mimeType + name = fileListResponse.name + path = fileListResponse.path + size = fileListResponse.size + source = fileListResponse.source + tags = fileListResponse.tags.map { it.toMutableList() } + updatedAt = fileListResponse.updatedAt + url = fileListResponse.url + width = fileListResponse.width + additionalProperties = fileListResponse.additionalProperties.toMutableMap() } - fun isValid(): Boolean = - try { - validate() - true - } catch (e: AutorenderInvalidDataException) { - false - } + fun id(id: String) = id(JsonField.of(id)) /** - * Returns a score indicating how many valid values are contained in this object - * recursively. + * Sets [Builder.id] to an arbitrary JSON value. * - * Used for best match union deserialization. + * You should usually call [Builder.id] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - @JvmSynthetic - internal fun validity(): Int = - (if (id.asKnown().isPresent) 1 else 0) + - (if (createdAt.asKnown().isPresent) 1 else 0) + - (if (fileNo.asKnown().isPresent) 1 else 0) + - (if (folderName.asKnown().isPresent) 1 else 0) + - (if (folderNo.asKnown().isPresent) 1 else 0) + - (if (format.asKnown().isPresent) 1 else 0) + - (if (height.asKnown().isPresent) 1 else 0) + - (metadata.asKnown().getOrNull()?.validity() ?: 0) + - (if (mimeType.asKnown().isPresent) 1 else 0) + - (if (name.asKnown().isPresent) 1 else 0) + - (if (path.asKnown().isPresent) 1 else 0) + - (if (size.asKnown().isPresent) 1 else 0) + - (if (source.asKnown().isPresent) 1 else 0) + - (tags.asKnown().getOrNull()?.size ?: 0) + - (if (updatedAt.asKnown().isPresent) 1 else 0) + - (if (url.asKnown().isPresent) 1 else 0) + - (if (width.asKnown().isPresent) 1 else 0) - - class Metadata - @JsonCreator - private constructor( - @com.fasterxml.jackson.annotation.JsonValue - private val additionalProperties: Map - ) { - - @JsonAnyGetter - @ExcludeMissing - fun _additionalProperties(): Map = additionalProperties - - fun toBuilder() = Builder().from(this) - - companion object { - - /** Returns a mutable builder for constructing an instance of [Metadata]. */ - @JvmStatic fun builder() = Builder() - } - - /** A builder for [Metadata]. */ - class Builder internal constructor() { + fun id(id: JsonField) = apply { this.id = id } - private var additionalProperties: MutableMap = mutableMapOf() + fun createdAt(createdAt: OffsetDateTime) = createdAt(JsonField.of(createdAt)) - @JvmSynthetic - internal fun from(metadata: Metadata) = apply { - additionalProperties = metadata.additionalProperties.toMutableMap() - } + /** + * Sets [Builder.createdAt] to an arbitrary JSON value. + * + * You should usually call [Builder.createdAt] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun createdAt(createdAt: JsonField) = apply { this.createdAt = createdAt } - fun additionalProperties(additionalProperties: Map) = apply { - this.additionalProperties.clear() - putAllAdditionalProperties(additionalProperties) - } + fun fileNo(fileNo: String) = fileNo(JsonField.of(fileNo)) - fun putAdditionalProperty(key: String, value: JsonValue) = apply { - additionalProperties.put(key, value) - } + /** + * Sets [Builder.fileNo] to an arbitrary JSON value. + * + * You should usually call [Builder.fileNo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun fileNo(fileNo: JsonField) = apply { this.fileNo = fileNo } - fun putAllAdditionalProperties(additionalProperties: Map) = - apply { - this.additionalProperties.putAll(additionalProperties) - } + fun folderName(folderName: String?) = folderName(JsonField.ofNullable(folderName)) - fun removeAdditionalProperty(key: String) = apply { - additionalProperties.remove(key) - } + /** Alias for calling [Builder.folderName] with `folderName.orElse(null)`. */ + fun folderName(folderName: Optional) = folderName(folderName.getOrNull()) - fun removeAllAdditionalProperties(keys: Set) = apply { - keys.forEach(::removeAdditionalProperty) - } + /** + * Sets [Builder.folderName] to an arbitrary JSON value. + * + * You should usually call [Builder.folderName] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun folderName(folderName: JsonField) = apply { this.folderName = folderName } - /** - * Returns an immutable instance of [Metadata]. - * - * Further updates to this [Builder] will not mutate the returned instance. - */ - fun build(): Metadata = Metadata(additionalProperties.toImmutable()) - } + fun folderNo(folderNo: String?) = folderNo(JsonField.ofNullable(folderNo)) - private var validated: Boolean = false + /** Alias for calling [Builder.folderNo] with `folderNo.orElse(null)`. */ + fun folderNo(folderNo: Optional) = folderNo(folderNo.getOrNull()) - /** - * Validates that the types of all values in this object match their expected types - * recursively. - * - * This method is _not_ forwards compatible with new types from the API for existing - * fields. - * - * @throws AutorenderInvalidDataException if any value type in this object doesn't match - * its expected type. - */ - fun validate(): Metadata = apply { - if (validated) { - return@apply - } + /** + * Sets [Builder.folderNo] to an arbitrary JSON value. + * + * You should usually call [Builder.folderNo] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun folderNo(folderNo: JsonField) = apply { this.folderNo = folderNo } - validated = true - } + fun format(format: String?) = format(JsonField.ofNullable(format)) - fun isValid(): Boolean = - try { - validate() - true - } catch (e: AutorenderInvalidDataException) { - false - } + /** Alias for calling [Builder.format] with `format.orElse(null)`. */ + fun format(format: Optional) = format(format.getOrNull()) - /** - * Returns a score indicating how many valid values are contained in this object - * recursively. - * - * Used for best match union deserialization. - */ - @JvmSynthetic - internal fun validity(): Int = - additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } + /** + * Sets [Builder.format] to an arbitrary JSON value. + * + * You should usually call [Builder.format] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun format(format: JsonField) = apply { this.format = format } - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + fun height(height: Long?) = height(JsonField.ofNullable(height)) - return other is Metadata && additionalProperties == other.additionalProperties - } + /** + * Alias for [Builder.height]. + * + * This unboxed primitive overload exists for backwards compatibility. + */ + fun height(height: Long) = height(height as Long?) - private val hashCode: Int by lazy { Objects.hash(additionalProperties) } + /** Alias for calling [Builder.height] with `height.orElse(null)`. */ + fun height(height: Optional) = height(height.getOrNull()) - override fun hashCode(): Int = hashCode + /** + * Sets [Builder.height] to an arbitrary JSON value. + * + * You should usually call [Builder.height] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun height(height: JsonField) = apply { this.height = height } - override fun toString() = "Metadata{additionalProperties=$additionalProperties}" - } + fun metadata(metadata: Metadata?) = metadata(JsonField.ofNullable(metadata)) - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } + /** Alias for calling [Builder.metadata] with `metadata.orElse(null)`. */ + fun metadata(metadata: Optional) = metadata(metadata.getOrNull()) - return other is File && - id == other.id && - createdAt == other.createdAt && - fileNo == other.fileNo && - folderName == other.folderName && - folderNo == other.folderNo && - format == other.format && - height == other.height && - metadata == other.metadata && - mimeType == other.mimeType && - name == other.name && - path == other.path && - size == other.size && - source == other.source && - tags == other.tags && - updatedAt == other.updatedAt && - url == other.url && - width == other.width && - additionalProperties == other.additionalProperties - } + /** + * Sets [Builder.metadata] to an arbitrary JSON value. + * + * You should usually call [Builder.metadata] with a well-typed [Metadata] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun metadata(metadata: JsonField) = apply { this.metadata = metadata } - private val hashCode: Int by lazy { - Objects.hash( - id, - createdAt, - fileNo, - folderName, - folderNo, - format, - height, - metadata, - mimeType, - name, - path, - size, - source, - tags, - updatedAt, - url, - width, - additionalProperties, - ) - } + fun mimeType(mimeType: String) = mimeType(JsonField.of(mimeType)) - override fun hashCode(): Int = hashCode + /** + * Sets [Builder.mimeType] to an arbitrary JSON value. + * + * You should usually call [Builder.mimeType] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun mimeType(mimeType: JsonField) = apply { this.mimeType = mimeType } - override fun toString() = - "File{id=$id, createdAt=$createdAt, fileNo=$fileNo, folderName=$folderName, folderNo=$folderNo, format=$format, height=$height, metadata=$metadata, mimeType=$mimeType, name=$name, path=$path, size=$size, source=$source, tags=$tags, updatedAt=$updatedAt, url=$url, width=$width, additionalProperties=$additionalProperties}" - } + fun name(name: String) = name(JsonField.of(name)) - class Meta - @JsonCreator(mode = JsonCreator.Mode.DISABLED) - private constructor( - private val hasNext: JsonField, - private val hasPrev: JsonField, - private val limit: JsonField, - private val page: JsonField, - private val total: JsonField, - private val additionalProperties: MutableMap, - ) { + /** + * Sets [Builder.name] to an arbitrary JSON value. + * + * You should usually call [Builder.name] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. + */ + fun name(name: JsonField) = apply { this.name = name } - @JsonCreator - private constructor( - @JsonProperty("hasNext") @ExcludeMissing hasNext: JsonField = JsonMissing.of(), - @JsonProperty("hasPrev") @ExcludeMissing hasPrev: JsonField = JsonMissing.of(), - @JsonProperty("limit") @ExcludeMissing limit: JsonField = JsonMissing.of(), - @JsonProperty("page") @ExcludeMissing page: JsonField = JsonMissing.of(), - @JsonProperty("total") @ExcludeMissing total: JsonField = JsonMissing.of(), - ) : this(hasNext, hasPrev, limit, page, total, mutableMapOf()) + fun path(path: String) = path(JsonField.of(path)) /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + * Sets [Builder.path] to an arbitrary JSON value. + * + * You should usually call [Builder.path] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun hasNext(): Boolean = hasNext.getRequired("hasNext") + fun path(path: JsonField) = apply { this.path = path } + + fun size(size: Long) = size(JsonField.of(size)) /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + * Sets [Builder.size] to an arbitrary JSON value. + * + * You should usually call [Builder.size] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun hasPrev(): Boolean = hasPrev.getRequired("hasPrev") + fun size(size: JsonField) = apply { this.size = size } + + fun source(source: String) = source(JsonField.of(source)) /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + * Sets [Builder.source] to an arbitrary JSON value. + * + * You should usually call [Builder.source] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - fun limit(): Long = limit.getRequired("limit") + fun source(source: JsonField) = apply { this.source = source } + + fun tags(tags: List) = tags(JsonField.of(tags)) /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + * Sets [Builder.tags] to an arbitrary JSON value. + * + * You should usually call [Builder.tags] with a well-typed `List` value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. */ - fun page(): Long = page.getRequired("page") + fun tags(tags: JsonField>) = apply { + this.tags = tags.map { it.toMutableList() } + } /** - * @throws AutorenderInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). + * Adds a single [String] to [tags]. + * + * @throws IllegalStateException if the field was previously set to a non-list. */ - fun total(): Long = total.getRequired("total") + fun addTag(tag: String) = apply { + tags = (tags ?: JsonField.of(mutableListOf())).also { checkKnown("tags", it).add(tag) } + } + + fun updatedAt(updatedAt: OffsetDateTime?) = updatedAt(JsonField.ofNullable(updatedAt)) + + /** Alias for calling [Builder.updatedAt] with `updatedAt.orElse(null)`. */ + fun updatedAt(updatedAt: Optional) = updatedAt(updatedAt.getOrNull()) /** - * Returns the raw JSON value of [hasNext]. + * Sets [Builder.updatedAt] to an arbitrary JSON value. * - * Unlike [hasNext], this method doesn't throw if the JSON field has an unexpected type. + * You should usually call [Builder.updatedAt] with a well-typed [OffsetDateTime] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. */ - @JsonProperty("hasNext") @ExcludeMissing fun _hasNext(): JsonField = hasNext + fun updatedAt(updatedAt: JsonField) = apply { this.updatedAt = updatedAt } + + fun url(url: String) = url(JsonField.of(url)) /** - * Returns the raw JSON value of [hasPrev]. + * Sets [Builder.url] to an arbitrary JSON value. * - * Unlike [hasPrev], this method doesn't throw if the JSON field has an unexpected type. + * You should usually call [Builder.url] with a well-typed [String] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - @JsonProperty("hasPrev") @ExcludeMissing fun _hasPrev(): JsonField = hasPrev + fun url(url: JsonField) = apply { this.url = url } + + fun width(width: Long?) = width(JsonField.ofNullable(width)) /** - * Returns the raw JSON value of [limit]. + * Alias for [Builder.width]. * - * Unlike [limit], this method doesn't throw if the JSON field has an unexpected type. + * This unboxed primitive overload exists for backwards compatibility. */ - @JsonProperty("limit") @ExcludeMissing fun _limit(): JsonField = limit + fun width(width: Long) = width(width as Long?) + + /** Alias for calling [Builder.width] with `width.orElse(null)`. */ + fun width(width: Optional) = width(width.getOrNull()) /** - * Returns the raw JSON value of [page]. + * Sets [Builder.width] to an arbitrary JSON value. * - * Unlike [page], this method doesn't throw if the JSON field has an unexpected type. + * You should usually call [Builder.width] with a well-typed [Long] value instead. This + * method is primarily for setting the field to an undocumented or not yet supported value. */ - @JsonProperty("page") @ExcludeMissing fun _page(): JsonField = page + fun width(width: JsonField) = apply { this.width = width } + + fun additionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.clear() + putAllAdditionalProperties(additionalProperties) + } + + fun putAdditionalProperty(key: String, value: JsonValue) = apply { + additionalProperties.put(key, value) + } + + fun putAllAdditionalProperties(additionalProperties: Map) = apply { + this.additionalProperties.putAll(additionalProperties) + } + + fun removeAdditionalProperty(key: String) = apply { additionalProperties.remove(key) } + + fun removeAllAdditionalProperties(keys: Set) = apply { + keys.forEach(::removeAdditionalProperty) + } /** - * Returns the raw JSON value of [total]. + * Returns an immutable instance of [FileListResponse]. + * + * Further updates to this [Builder] will not mutate the returned instance. * - * Unlike [total], this method doesn't throw if the JSON field has an unexpected type. + * The following fields are required: + * ```java + * .id() + * .createdAt() + * .fileNo() + * .folderName() + * .folderNo() + * .format() + * .height() + * .metadata() + * .mimeType() + * .name() + * .path() + * .size() + * .source() + * .tags() + * .updatedAt() + * .url() + * .width() + * ``` + * + * @throws IllegalStateException if any required field is unset. */ - @JsonProperty("total") @ExcludeMissing fun _total(): JsonField = total + fun build(): FileListResponse = + FileListResponse( + checkRequired("id", id), + checkRequired("createdAt", createdAt), + checkRequired("fileNo", fileNo), + checkRequired("folderName", folderName), + checkRequired("folderNo", folderNo), + checkRequired("format", format), + checkRequired("height", height), + checkRequired("metadata", metadata), + checkRequired("mimeType", mimeType), + checkRequired("name", name), + checkRequired("path", path), + checkRequired("size", size), + checkRequired("source", source), + checkRequired("tags", tags).map { it.toImmutable() }, + checkRequired("updatedAt", updatedAt), + checkRequired("url", url), + checkRequired("width", width), + additionalProperties.toMutableMap(), + ) + } - @JsonAnySetter - private fun putAdditionalProperty(key: String, value: JsonValue) { - additionalProperties.put(key, value) + private var validated: Boolean = false + + /** + * Validates that the types of all values in this object match their expected types recursively. + * + * This method is _not_ forwards compatible with new types from the API for existing fields. + * + * @throws AutorenderInvalidDataException if any value type in this object doesn't match its + * expected type. + */ + fun validate(): FileListResponse = apply { + if (validated) { + return@apply + } + + id() + createdAt() + fileNo() + folderName() + folderNo() + format() + height() + metadata().ifPresent { it.validate() } + mimeType() + name() + path() + size() + source() + tags() + updatedAt() + url() + width() + validated = true + } + + fun isValid(): Boolean = + try { + validate() + true + } catch (e: AutorenderInvalidDataException) { + false } + /** + * Returns a score indicating how many valid values are contained in this object recursively. + * + * Used for best match union deserialization. + */ + @JvmSynthetic + internal fun validity(): Int = + (if (id.asKnown().isPresent) 1 else 0) + + (if (createdAt.asKnown().isPresent) 1 else 0) + + (if (fileNo.asKnown().isPresent) 1 else 0) + + (if (folderName.asKnown().isPresent) 1 else 0) + + (if (folderNo.asKnown().isPresent) 1 else 0) + + (if (format.asKnown().isPresent) 1 else 0) + + (if (height.asKnown().isPresent) 1 else 0) + + (metadata.asKnown().getOrNull()?.validity() ?: 0) + + (if (mimeType.asKnown().isPresent) 1 else 0) + + (if (name.asKnown().isPresent) 1 else 0) + + (if (path.asKnown().isPresent) 1 else 0) + + (if (size.asKnown().isPresent) 1 else 0) + + (if (source.asKnown().isPresent) 1 else 0) + + (tags.asKnown().getOrNull()?.size ?: 0) + + (if (updatedAt.asKnown().isPresent) 1 else 0) + + (if (url.asKnown().isPresent) 1 else 0) + + (if (width.asKnown().isPresent) 1 else 0) + + class Metadata + @JsonCreator + private constructor( + @com.fasterxml.jackson.annotation.JsonValue + private val additionalProperties: Map + ) { + @JsonAnyGetter @ExcludeMissing - fun _additionalProperties(): Map = - Collections.unmodifiableMap(additionalProperties) + fun _additionalProperties(): Map = additionalProperties fun toBuilder() = Builder().from(this) companion object { - /** - * Returns a mutable builder for constructing an instance of [Meta]. - * - * The following fields are required: - * ```java - * .hasNext() - * .hasPrev() - * .limit() - * .page() - * .total() - * ``` - */ + /** Returns a mutable builder for constructing an instance of [Metadata]. */ @JvmStatic fun builder() = Builder() } - /** A builder for [Meta]. */ + /** A builder for [Metadata]. */ class Builder internal constructor() { - private var hasNext: JsonField? = null - private var hasPrev: JsonField? = null - private var limit: JsonField? = null - private var page: JsonField? = null - private var total: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic - internal fun from(meta: Meta) = apply { - hasNext = meta.hasNext - hasPrev = meta.hasPrev - limit = meta.limit - page = meta.page - total = meta.total - additionalProperties = meta.additionalProperties.toMutableMap() + internal fun from(metadata: Metadata) = apply { + additionalProperties = metadata.additionalProperties.toMutableMap() } - fun hasNext(hasNext: Boolean) = hasNext(JsonField.of(hasNext)) - - /** - * Sets [Builder.hasNext] to an arbitrary JSON value. - * - * You should usually call [Builder.hasNext] with a well-typed [Boolean] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun hasNext(hasNext: JsonField) = apply { this.hasNext = hasNext } - - fun hasPrev(hasPrev: Boolean) = hasPrev(JsonField.of(hasPrev)) - - /** - * Sets [Builder.hasPrev] to an arbitrary JSON value. - * - * You should usually call [Builder.hasPrev] with a well-typed [Boolean] value instead. - * This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun hasPrev(hasPrev: JsonField) = apply { this.hasPrev = hasPrev } - - fun limit(limit: Long) = limit(JsonField.of(limit)) - - /** - * Sets [Builder.limit] to an arbitrary JSON value. - * - * You should usually call [Builder.limit] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun limit(limit: JsonField) = apply { this.limit = limit } - - fun page(page: Long) = page(JsonField.of(page)) - - /** - * Sets [Builder.page] to an arbitrary JSON value. - * - * You should usually call [Builder.page] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun page(page: JsonField) = apply { this.page = page } - - fun total(total: Long) = total(JsonField.of(total)) - - /** - * Sets [Builder.total] to an arbitrary JSON value. - * - * You should usually call [Builder.total] with a well-typed [Long] value instead. This - * method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun total(total: JsonField) = apply { this.total = total } - fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() putAllAdditionalProperties(additionalProperties) @@ -1353,30 +807,11 @@ private constructor( } /** - * Returns an immutable instance of [Meta]. + * Returns an immutable instance of [Metadata]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .hasNext() - * .hasPrev() - * .limit() - * .page() - * .total() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ - fun build(): Meta = - Meta( - checkRequired("hasNext", hasNext), - checkRequired("hasPrev", hasPrev), - checkRequired("limit", limit), - checkRequired("page", page), - checkRequired("total", total), - additionalProperties.toMutableMap(), - ) + fun build(): Metadata = Metadata(additionalProperties.toImmutable()) } private var validated: Boolean = false @@ -1390,16 +825,11 @@ private constructor( * @throws AutorenderInvalidDataException if any value type in this object doesn't match its * expected type. */ - fun validate(): Meta = apply { + fun validate(): Metadata = apply { if (validated) { return@apply } - hasNext() - hasPrev() - limit() - page() - total() validated = true } @@ -1419,34 +849,21 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (hasNext.asKnown().isPresent) 1 else 0) + - (if (hasPrev.asKnown().isPresent) 1 else 0) + - (if (limit.asKnown().isPresent) 1 else 0) + - (if (page.asKnown().isPresent) 1 else 0) + - (if (total.asKnown().isPresent) 1 else 0) + additionalProperties.count { (_, value) -> !value.isNull() && !value.isMissing() } override fun equals(other: Any?): Boolean { if (this === other) { return true } - return other is Meta && - hasNext == other.hasNext && - hasPrev == other.hasPrev && - limit == other.limit && - page == other.page && - total == other.total && - additionalProperties == other.additionalProperties + return other is Metadata && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { - Objects.hash(hasNext, hasPrev, limit, page, total, additionalProperties) - } + private val hashCode: Int by lazy { Objects.hash(additionalProperties) } override fun hashCode(): Int = hashCode - override fun toString() = - "Meta{hasNext=$hasNext, hasPrev=$hasPrev, limit=$limit, page=$page, total=$total, additionalProperties=$additionalProperties}" + override fun toString() = "Metadata{additionalProperties=$additionalProperties}" } override fun equals(other: Any?): Boolean { @@ -1455,15 +872,51 @@ private constructor( } return other is FileListResponse && - files == other.files && - meta == other.meta && + id == other.id && + createdAt == other.createdAt && + fileNo == other.fileNo && + folderName == other.folderName && + folderNo == other.folderNo && + format == other.format && + height == other.height && + metadata == other.metadata && + mimeType == other.mimeType && + name == other.name && + path == other.path && + size == other.size && + source == other.source && + tags == other.tags && + updatedAt == other.updatedAt && + url == other.url && + width == other.width && additionalProperties == other.additionalProperties } - private val hashCode: Int by lazy { Objects.hash(files, meta, additionalProperties) } + private val hashCode: Int by lazy { + Objects.hash( + id, + createdAt, + fileNo, + folderName, + folderNo, + format, + height, + metadata, + mimeType, + name, + path, + size, + source, + tags, + updatedAt, + url, + width, + additionalProperties, + ) + } override fun hashCode(): Int = hashCode override fun toString() = - "FileListResponse{files=$files, meta=$meta, additionalProperties=$additionalProperties}" + "FileListResponse{id=$id, createdAt=$createdAt, fileNo=$fileNo, folderName=$folderName, folderNo=$folderNo, format=$format, height=$height, metadata=$metadata, mimeType=$mimeType, name=$name, path=$path, size=$size, source=$source, tags=$tags, updatedAt=$updatedAt, url=$url, width=$width, additionalProperties=$additionalProperties}" } diff --git a/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsync.kt b/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsync.kt index 5813393..ff925df 100644 --- a/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsync.kt +++ b/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsync.kt @@ -7,8 +7,8 @@ import io.autorender.core.RequestOptions import io.autorender.core.http.HttpResponse import io.autorender.core.http.HttpResponseFor import io.autorender.models.files.FileDeleteParams +import io.autorender.models.files.FileListPageAsync import io.autorender.models.files.FileListParams -import io.autorender.models.files.FileListResponse import io.autorender.models.files.FileRenameParams import io.autorender.models.files.FileRenameResponse import io.autorender.models.files.FileRetrieveParams @@ -67,20 +67,20 @@ interface FileServiceAsync { retrieve(fileNo, FileRetrieveParams.none(), requestOptions) /** List/search files with pagination, filtering, and sorting. */ - fun list(): CompletableFuture = list(FileListParams.none()) + fun list(): CompletableFuture = list(FileListParams.none()) /** @see list */ fun list( params: FileListParams = FileListParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture + ): CompletableFuture /** @see list */ - fun list(params: FileListParams = FileListParams.none()): CompletableFuture = + fun list(params: FileListParams = FileListParams.none()): CompletableFuture = list(params, RequestOptions.none()) /** @see list */ - fun list(requestOptions: RequestOptions): CompletableFuture = + fun list(requestOptions: RequestOptions): CompletableFuture = list(FileListParams.none(), requestOptions) /** Delete file */ @@ -190,25 +190,25 @@ interface FileServiceAsync { * Returns a raw HTTP response for `get /api/v1/files`, but is otherwise the same as * [FileServiceAsync.list]. */ - fun list(): CompletableFuture> = + fun list(): CompletableFuture> = list(FileListParams.none()) /** @see list */ fun list( params: FileListParams = FileListParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + ): CompletableFuture> /** @see list */ fun list( params: FileListParams = FileListParams.none() - ): CompletableFuture> = + ): CompletableFuture> = list(params, RequestOptions.none()) /** @see list */ fun list( requestOptions: RequestOptions - ): CompletableFuture> = + ): CompletableFuture> = list(FileListParams.none(), requestOptions) /** diff --git a/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsyncImpl.kt b/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsyncImpl.kt index 51fb0f7..1a1b689 100644 --- a/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsyncImpl.kt +++ b/autorender-java-core/src/main/kotlin/io/autorender/services/async/FileServiceAsyncImpl.kt @@ -18,8 +18,9 @@ import io.autorender.core.http.json import io.autorender.core.http.parseable import io.autorender.core.prepareAsync import io.autorender.models.files.FileDeleteParams +import io.autorender.models.files.FileListPageAsync +import io.autorender.models.files.FileListPageResponse import io.autorender.models.files.FileListParams -import io.autorender.models.files.FileListResponse import io.autorender.models.files.FileRenameParams import io.autorender.models.files.FileRenameResponse import io.autorender.models.files.FileRetrieveParams @@ -51,7 +52,7 @@ class FileServiceAsyncImpl internal constructor(private val clientOptions: Clien override fun list( params: FileListParams, requestOptions: RequestOptions, - ): CompletableFuture = + ): CompletableFuture = // get /api/v1/files withRawResponse().list(params, requestOptions).thenApply { it.parse() } @@ -115,13 +116,13 @@ class FileServiceAsyncImpl internal constructor(private val clientOptions: Clien } } - private val listHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun list( params: FileListParams, requestOptions: RequestOptions, - ): CompletableFuture> { + ): CompletableFuture> { val request = HttpRequest.builder() .method(HttpMethod.GET) @@ -141,6 +142,14 @@ class FileServiceAsyncImpl internal constructor(private val clientOptions: Clien it.validate() } } + .let { + FileListPageAsync.builder() + .service(FileServiceAsyncImpl(clientOptions)) + .streamHandlerExecutor(clientOptions.streamHandlerExecutor) + .params(params) + .response(it) + .build() + } } } } diff --git a/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileService.kt b/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileService.kt index 17aae69..c90b4cb 100644 --- a/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileService.kt +++ b/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileService.kt @@ -8,8 +8,8 @@ import io.autorender.core.RequestOptions import io.autorender.core.http.HttpResponse import io.autorender.core.http.HttpResponseFor import io.autorender.models.files.FileDeleteParams +import io.autorender.models.files.FileListPage import io.autorender.models.files.FileListParams -import io.autorender.models.files.FileListResponse import io.autorender.models.files.FileRenameParams import io.autorender.models.files.FileRenameResponse import io.autorender.models.files.FileRetrieveParams @@ -62,20 +62,20 @@ interface FileService { retrieve(fileNo, FileRetrieveParams.none(), requestOptions) /** List/search files with pagination, filtering, and sorting. */ - fun list(): FileListResponse = list(FileListParams.none()) + fun list(): FileListPage = list(FileListParams.none()) /** @see list */ fun list( params: FileListParams = FileListParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): FileListResponse + ): FileListPage /** @see list */ - fun list(params: FileListParams = FileListParams.none()): FileListResponse = + fun list(params: FileListParams = FileListParams.none()): FileListPage = list(params, RequestOptions.none()) /** @see list */ - fun list(requestOptions: RequestOptions): FileListResponse = + fun list(requestOptions: RequestOptions): FileListPage = list(FileListParams.none(), requestOptions) /** Delete file */ @@ -180,24 +180,23 @@ interface FileService { * Returns a raw HTTP response for `get /api/v1/files`, but is otherwise the same as * [FileService.list]. */ - @MustBeClosed fun list(): HttpResponseFor = list(FileListParams.none()) + @MustBeClosed fun list(): HttpResponseFor = list(FileListParams.none()) /** @see list */ @MustBeClosed fun list( params: FileListParams = FileListParams.none(), requestOptions: RequestOptions = RequestOptions.none(), - ): HttpResponseFor + ): HttpResponseFor /** @see list */ @MustBeClosed - fun list( - params: FileListParams = FileListParams.none() - ): HttpResponseFor = list(params, RequestOptions.none()) + fun list(params: FileListParams = FileListParams.none()): HttpResponseFor = + list(params, RequestOptions.none()) /** @see list */ @MustBeClosed - fun list(requestOptions: RequestOptions): HttpResponseFor = + fun list(requestOptions: RequestOptions): HttpResponseFor = list(FileListParams.none(), requestOptions) /** diff --git a/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileServiceImpl.kt b/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileServiceImpl.kt index 43898e2..344e2e6 100644 --- a/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileServiceImpl.kt +++ b/autorender-java-core/src/main/kotlin/io/autorender/services/blocking/FileServiceImpl.kt @@ -18,8 +18,9 @@ import io.autorender.core.http.json import io.autorender.core.http.parseable import io.autorender.core.prepare import io.autorender.models.files.FileDeleteParams +import io.autorender.models.files.FileListPage +import io.autorender.models.files.FileListPageResponse import io.autorender.models.files.FileListParams -import io.autorender.models.files.FileListResponse import io.autorender.models.files.FileRenameParams import io.autorender.models.files.FileRenameResponse import io.autorender.models.files.FileRetrieveParams @@ -46,7 +47,7 @@ class FileServiceImpl internal constructor(private val clientOptions: ClientOpti // get /api/v1/files/{fileNo} withRawResponse().retrieve(params, requestOptions).parse() - override fun list(params: FileListParams, requestOptions: RequestOptions): FileListResponse = + override fun list(params: FileListParams, requestOptions: RequestOptions): FileListPage = // get /api/v1/files withRawResponse().list(params, requestOptions).parse() @@ -105,13 +106,13 @@ class FileServiceImpl internal constructor(private val clientOptions: ClientOpti } } - private val listHandler: Handler = - jsonHandler(clientOptions.jsonMapper) + private val listHandler: Handler = + jsonHandler(clientOptions.jsonMapper) override fun list( params: FileListParams, requestOptions: RequestOptions, - ): HttpResponseFor { + ): HttpResponseFor { val request = HttpRequest.builder() .method(HttpMethod.GET) @@ -129,6 +130,13 @@ class FileServiceImpl internal constructor(private val clientOptions: ClientOpti it.validate() } } + .let { + FileListPage.builder() + .service(FileServiceImpl(clientOptions)) + .params(params) + .response(it) + .build() + } } } diff --git a/autorender-java-core/src/test/kotlin/io/autorender/core/AutoPagerAsyncTest.kt b/autorender-java-core/src/test/kotlin/io/autorender/core/AutoPagerAsyncTest.kt new file mode 100644 index 0000000..09db952 --- /dev/null +++ b/autorender-java-core/src/test/kotlin/io/autorender/core/AutoPagerAsyncTest.kt @@ -0,0 +1,182 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.core + +import io.autorender.core.http.AsyncStreamResponse +import java.util.Optional +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.catchThrowable +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.mockito.junit.jupiter.MockitoExtension +import org.mockito.kotlin.any +import org.mockito.kotlin.clearInvocations +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.inOrder +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.spy +import org.mockito.kotlin.times +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever + +@ExtendWith(MockitoExtension::class) +internal class AutoPagerAsyncTest { + + companion object { + + private val ERROR = RuntimeException("ERROR!") + } + + private class PageAsyncImpl( + private val items: List, + private val hasNext: Boolean = true, + ) : PageAsync { + + val nextPageFuture: CompletableFuture> = CompletableFuture() + + override fun hasNextPage(): Boolean = hasNext + + override fun nextPage(): CompletableFuture> = nextPageFuture + + override fun items(): List = items + } + + private val executor = + spy { + doAnswer { invocation -> invocation.getArgument(0).run() } + .whenever(it) + .execute(any()) + } + private val handler = mock>() + + @Test + fun subscribe_whenAlreadySubscribed_throws() { + val autoPagerAsync = AutoPagerAsync.from(PageAsyncImpl(emptyList()), executor) + autoPagerAsync.subscribe {} + clearInvocations(executor) + + val throwable = catchThrowable { autoPagerAsync.subscribe {} } + + assertThat(throwable).isInstanceOf(IllegalStateException::class.java) + assertThat(throwable).hasMessage("Cannot subscribe more than once") + verify(executor, never()).execute(any()) + } + + @Test + fun subscribe_whenClosed_throws() { + val autoPagerAsync = AutoPagerAsync.from(PageAsyncImpl(emptyList()), executor) + autoPagerAsync.close() + + val throwable = catchThrowable { autoPagerAsync.subscribe {} } + + assertThat(throwable).isInstanceOf(IllegalStateException::class.java) + assertThat(throwable).hasMessage("Cannot subscribe after the response is closed") + verify(executor, never()).execute(any()) + } + + @Test + fun subscribe_whenFirstPageNonEmpty_runsHandler() { + val page = PageAsyncImpl(listOf("item1", "item2", "item3"), hasNext = false) + val autoPagerAsync = AutoPagerAsync.from(page, executor) + + autoPagerAsync.subscribe(handler) + + inOrder(executor, handler) { + verify(executor, times(1)).execute(any()) + verify(handler, times(1)).onNext("item1") + verify(handler, times(1)).onNext("item2") + verify(handler, times(1)).onNext("item3") + verify(handler, times(1)).onComplete(Optional.empty()) + } + } + + @Test + fun subscribe_whenFutureCompletesAfterClose_doesNothing() { + val page = PageAsyncImpl(listOf("page1")) + val autoPagerAsync = AutoPagerAsync.from(page, executor) + autoPagerAsync.subscribe(handler) + autoPagerAsync.close() + + page.nextPageFuture.complete(PageAsyncImpl(listOf("page2"))) + + verify(handler, times(1)).onNext("page1") + verify(handler, never()).onNext("page2") + verify(handler, times(1)).onComplete(Optional.empty()) + verify(executor, times(1)).execute(any()) + } + + @Test + fun subscribe_whenFutureErrors_callsOnComplete() { + val page = PageAsyncImpl(emptyList()) + val autoPagerAsync = AutoPagerAsync.from(page, executor) + autoPagerAsync.subscribe(handler) + + page.nextPageFuture.completeExceptionally(ERROR) + + verify(executor, times(1)).execute(any()) + verify(handler, never()).onNext(any()) + verify(handler, times(1)).onComplete(Optional.of(ERROR)) + } + + @Test + fun subscribe_whenFutureCompletes_runsHandler() { + val page = PageAsyncImpl(listOf("chunk1", "chunk2")) + val autoPagerAsync = AutoPagerAsync.from(page, executor) + + autoPagerAsync.subscribe(handler) + + verify(handler, never()).onComplete(any()) + inOrder(executor, handler) { + verify(executor, times(1)).execute(any()) + verify(handler, times(1)).onNext("chunk1") + verify(handler, times(1)).onNext("chunk2") + } + clearInvocations(executor, handler) + + page.nextPageFuture.complete(PageAsyncImpl(listOf("chunk3", "chunk4"), hasNext = false)) + + verify(executor, never()).execute(any()) + inOrder(handler) { + verify(handler, times(1)).onNext("chunk3") + verify(handler, times(1)).onNext("chunk4") + verify(handler, times(1)).onComplete(Optional.empty()) + } + } + + @Test + fun onCompleteFuture_whenNextPageFutureNotCompleted_onCompleteFutureNotCompleted() { + val page = PageAsyncImpl(listOf("chunk1", "chunk2")) + val autoPagerAsync = AutoPagerAsync.from(page, executor) + autoPagerAsync.subscribe {} + + val onCompletableFuture = autoPagerAsync.onCompleteFuture() + + assertThat(onCompletableFuture).isNotCompleted + } + + @Test + fun onCompleteFuture_whenNextPageFutureErrors_onCompleteFutureCompletedExceptionally() { + val page = PageAsyncImpl(listOf("chunk1", "chunk2")) + val autoPagerAsync = AutoPagerAsync.from(page, executor) + autoPagerAsync.subscribe {} + page.nextPageFuture.completeExceptionally(ERROR) + + val onCompletableFuture = autoPagerAsync.onCompleteFuture() + + assertThat(onCompletableFuture).isCompletedExceptionally + } + + @Test + fun onCompleteFuture_whenNoNextPage_onCompleteFutureCompleted() { + val page = PageAsyncImpl(listOf("chunk1", "chunk2"), hasNext = false) + val autoPagerAsync = AutoPagerAsync.from(page, executor) + autoPagerAsync.subscribe {} + + val onCompletableFuture = autoPagerAsync.onCompleteFuture() + + assertThat(onCompletableFuture).isCompleted + } +} diff --git a/autorender-java-core/src/test/kotlin/io/autorender/core/AutoPagerTest.kt b/autorender-java-core/src/test/kotlin/io/autorender/core/AutoPagerTest.kt new file mode 100644 index 0000000..053fc5d --- /dev/null +++ b/autorender-java-core/src/test/kotlin/io/autorender/core/AutoPagerTest.kt @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.core + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class AutoPagerTest { + + private class PageImpl( + private val items: List, + private val nextPage: Page? = null, + ) : Page { + + override fun hasNextPage(): Boolean = nextPage != null + + override fun nextPage(): Page = nextPage!! + + override fun items(): List = items + } + + @Test + fun iterator() { + val firstPage = + PageImpl(listOf("chunk1", "chunk2"), nextPage = PageImpl(listOf("chunk3", "chunk4"))) + + val autoPager = AutoPager.from(firstPage) + + assertThat(autoPager).containsExactly("chunk1", "chunk2", "chunk3", "chunk4") + } + + @Test + fun stream() { + val firstPage = + PageImpl(listOf("chunk1", "chunk2"), nextPage = PageImpl(listOf("chunk3", "chunk4"))) + + val autoPager = AutoPager.from(firstPage) + + assertThat(autoPager.stream()).containsExactly("chunk1", "chunk2", "chunk3", "chunk4") + } +} diff --git a/autorender-java-core/src/test/kotlin/io/autorender/models/files/FileListPageResponseTest.kt b/autorender-java-core/src/test/kotlin/io/autorender/models/files/FileListPageResponseTest.kt new file mode 100644 index 0000000..db4052a --- /dev/null +++ b/autorender-java-core/src/test/kotlin/io/autorender/models/files/FileListPageResponseTest.kt @@ -0,0 +1,141 @@ +// File generated from our OpenAPI spec by Stainless. + +package io.autorender.models.files + +import com.fasterxml.jackson.module.kotlin.jacksonTypeRef +import io.autorender.core.JsonValue +import io.autorender.core.jsonMapper +import java.time.OffsetDateTime +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class FileListPageResponseTest { + + @Test + fun create() { + val fileListPageResponse = + FileListPageResponse.builder() + .addFile( + FileListResponse.builder() + .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .fileNo("file_no") + .folderName("folder_name") + .folderNo("folder_no") + .format("format") + .height(-9007199254740991L) + .metadata( + FileListResponse.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .mimeType("mime_type") + .name("name") + .path("path") + .size(-9007199254740991L) + .source("source") + .addTag("string") + .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .url("url") + .width(-9007199254740991L) + .build() + ) + .meta( + FileListPageResponse.Meta.builder() + .hasNext(true) + .hasPrev(true) + .limit(-9007199254740991L) + .page(-9007199254740991L) + .total(-9007199254740991L) + .build() + ) + .build() + + assertThat(fileListPageResponse.files()) + .containsExactly( + FileListResponse.builder() + .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .fileNo("file_no") + .folderName("folder_name") + .folderNo("folder_no") + .format("format") + .height(-9007199254740991L) + .metadata( + FileListResponse.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .mimeType("mime_type") + .name("name") + .path("path") + .size(-9007199254740991L) + .source("source") + .addTag("string") + .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .url("url") + .width(-9007199254740991L) + .build() + ) + assertThat(fileListPageResponse.meta()) + .isEqualTo( + FileListPageResponse.Meta.builder() + .hasNext(true) + .hasPrev(true) + .limit(-9007199254740991L) + .page(-9007199254740991L) + .total(-9007199254740991L) + .build() + ) + } + + @Test + fun roundtrip() { + val jsonMapper = jsonMapper() + val fileListPageResponse = + FileListPageResponse.builder() + .addFile( + FileListResponse.builder() + .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .fileNo("file_no") + .folderName("folder_name") + .folderNo("folder_no") + .format("format") + .height(-9007199254740991L) + .metadata( + FileListResponse.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) + .build() + ) + .mimeType("mime_type") + .name("name") + .path("path") + .size(-9007199254740991L) + .source("source") + .addTag("string") + .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .url("url") + .width(-9007199254740991L) + .build() + ) + .meta( + FileListPageResponse.Meta.builder() + .hasNext(true) + .hasPrev(true) + .limit(-9007199254740991L) + .page(-9007199254740991L) + .total(-9007199254740991L) + .build() + ) + .build() + + val roundtrippedFileListPageResponse = + jsonMapper.readValue( + jsonMapper.writeValueAsString(fileListPageResponse), + jacksonTypeRef(), + ) + + assertThat(roundtrippedFileListPageResponse).isEqualTo(fileListPageResponse) + } +} diff --git a/autorender-java-core/src/test/kotlin/io/autorender/models/files/FileListResponseTest.kt b/autorender-java-core/src/test/kotlin/io/autorender/models/files/FileListResponseTest.kt index 1b1f07c..49ce6bd 100644 --- a/autorender-java-core/src/test/kotlin/io/autorender/models/files/FileListResponseTest.kt +++ b/autorender-java-core/src/test/kotlin/io/autorender/models/files/FileListResponseTest.kt @@ -15,78 +15,53 @@ internal class FileListResponseTest { fun create() { val fileListResponse = FileListResponse.builder() - .addFile( - FileListResponse.File.builder() - .id("id") - .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) - .fileNo("file_no") - .folderName("folder_name") - .folderNo("folder_no") - .format("format") - .height(-9007199254740991L) - .metadata( - FileListResponse.File.Metadata.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .mimeType("mime_type") - .name("name") - .path("path") - .size(-9007199254740991L) - .source("source") - .addTag("string") - .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) - .url("url") - .width(-9007199254740991L) - .build() - ) - .meta( - FileListResponse.Meta.builder() - .hasNext(true) - .hasPrev(true) - .limit(-9007199254740991L) - .page(-9007199254740991L) - .total(-9007199254740991L) + .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .fileNo("file_no") + .folderName("folder_name") + .folderNo("folder_no") + .format("format") + .height(-9007199254740991L) + .metadata( + FileListResponse.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .mimeType("mime_type") + .name("name") + .path("path") + .size(-9007199254740991L) + .source("source") + .addTag("string") + .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .url("url") + .width(-9007199254740991L) .build() - assertThat(fileListResponse.files()) - .containsExactly( - FileListResponse.File.builder() - .id("id") - .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) - .fileNo("file_no") - .folderName("folder_name") - .folderNo("folder_no") - .format("format") - .height(-9007199254740991L) - .metadata( - FileListResponse.File.Metadata.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .mimeType("mime_type") - .name("name") - .path("path") - .size(-9007199254740991L) - .source("source") - .addTag("string") - .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) - .url("url") - .width(-9007199254740991L) - .build() - ) - assertThat(fileListResponse.meta()) - .isEqualTo( - FileListResponse.Meta.builder() - .hasNext(true) - .hasPrev(true) - .limit(-9007199254740991L) - .page(-9007199254740991L) - .total(-9007199254740991L) + assertThat(fileListResponse.id()).isEqualTo("id") + assertThat(fileListResponse.createdAt()) + .isEqualTo(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(fileListResponse.fileNo()).isEqualTo("file_no") + assertThat(fileListResponse.folderName()).contains("folder_name") + assertThat(fileListResponse.folderNo()).contains("folder_no") + assertThat(fileListResponse.format()).contains("format") + assertThat(fileListResponse.height()).contains(-9007199254740991L) + assertThat(fileListResponse.metadata()) + .contains( + FileListResponse.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + assertThat(fileListResponse.mimeType()).isEqualTo("mime_type") + assertThat(fileListResponse.name()).isEqualTo("name") + assertThat(fileListResponse.path()).isEqualTo("path") + assertThat(fileListResponse.size()).isEqualTo(-9007199254740991L) + assertThat(fileListResponse.source()).isEqualTo("source") + assertThat(fileListResponse.tags()).containsExactly("string") + assertThat(fileListResponse.updatedAt()) + .contains(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + assertThat(fileListResponse.url()).isEqualTo("url") + assertThat(fileListResponse.width()).contains(-9007199254740991L) } @Test @@ -94,40 +69,27 @@ internal class FileListResponseTest { val jsonMapper = jsonMapper() val fileListResponse = FileListResponse.builder() - .addFile( - FileListResponse.File.builder() - .id("id") - .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) - .fileNo("file_no") - .folderName("folder_name") - .folderNo("folder_no") - .format("format") - .height(-9007199254740991L) - .metadata( - FileListResponse.File.Metadata.builder() - .putAdditionalProperty("foo", JsonValue.from("bar")) - .build() - ) - .mimeType("mime_type") - .name("name") - .path("path") - .size(-9007199254740991L) - .source("source") - .addTag("string") - .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) - .url("url") - .width(-9007199254740991L) - .build() - ) - .meta( - FileListResponse.Meta.builder() - .hasNext(true) - .hasPrev(true) - .limit(-9007199254740991L) - .page(-9007199254740991L) - .total(-9007199254740991L) + .id("id") + .createdAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .fileNo("file_no") + .folderName("folder_name") + .folderNo("folder_no") + .format("format") + .height(-9007199254740991L) + .metadata( + FileListResponse.Metadata.builder() + .putAdditionalProperty("foo", JsonValue.from("bar")) .build() ) + .mimeType("mime_type") + .name("name") + .path("path") + .size(-9007199254740991L) + .source("source") + .addTag("string") + .updatedAt(OffsetDateTime.parse("2019-12-27T18:11:19.117Z")) + .url("url") + .width(-9007199254740991L) .build() val roundtrippedFileListResponse = diff --git a/autorender-java-core/src/test/kotlin/io/autorender/services/ServiceParamsTest.kt b/autorender-java-core/src/test/kotlin/io/autorender/services/ServiceParamsTest.kt index 744c051..d3b5146 100644 --- a/autorender-java-core/src/test/kotlin/io/autorender/services/ServiceParamsTest.kt +++ b/autorender-java-core/src/test/kotlin/io/autorender/services/ServiceParamsTest.kt @@ -77,11 +77,6 @@ internal class ServiceParamsTest { fileService.list( FileListParams.builder() - .folderNo("folder_no") - .limit(1L) - .page(1L) - .search("search") - .sort(FileListParams.Sort.NAME_ASC) .putAdditionalHeader("Secret-Header", "42") .putAdditionalQueryParam("secret_query_param", "42") .build() diff --git a/autorender-java-core/src/test/kotlin/io/autorender/services/async/FileServiceAsyncTest.kt b/autorender-java-core/src/test/kotlin/io/autorender/services/async/FileServiceAsyncTest.kt index b9e21dc..9a1fc74 100644 --- a/autorender-java-core/src/test/kotlin/io/autorender/services/async/FileServiceAsyncTest.kt +++ b/autorender-java-core/src/test/kotlin/io/autorender/services/async/FileServiceAsyncTest.kt @@ -4,7 +4,6 @@ package io.autorender.services.async import io.autorender.TestServerExtension import io.autorender.client.okhttp.AutorenderOkHttpClientAsync -import io.autorender.models.files.FileListParams import io.autorender.models.files.FileRenameParams import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -36,19 +35,10 @@ internal class FileServiceAsyncTest { .build() val fileServiceAsync = client.files() - val filesFuture = - fileServiceAsync.list( - FileListParams.builder() - .folderNo("folder_no") - .limit(1L) - .page(1L) - .search("search") - .sort(FileListParams.Sort.NAME_ASC) - .build() - ) + val pageFuture = fileServiceAsync.list() - val files = filesFuture.get() - files.validate() + val page = pageFuture.get() + page.response().validate() } @Test diff --git a/autorender-java-core/src/test/kotlin/io/autorender/services/blocking/FileServiceTest.kt b/autorender-java-core/src/test/kotlin/io/autorender/services/blocking/FileServiceTest.kt index 3f9fbb6..35ab757 100644 --- a/autorender-java-core/src/test/kotlin/io/autorender/services/blocking/FileServiceTest.kt +++ b/autorender-java-core/src/test/kotlin/io/autorender/services/blocking/FileServiceTest.kt @@ -4,7 +4,6 @@ package io.autorender.services.blocking import io.autorender.TestServerExtension import io.autorender.client.okhttp.AutorenderOkHttpClient -import io.autorender.models.files.FileListParams import io.autorender.models.files.FileRenameParams import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -35,18 +34,9 @@ internal class FileServiceTest { .build() val fileService = client.files() - val files = - fileService.list( - FileListParams.builder() - .folderNo("folder_no") - .limit(1L) - .page(1L) - .search("search") - .sort(FileListParams.Sort.NAME_ASC) - .build() - ) + val page = fileService.list() - files.validate() + page.response().validate() } @Test diff --git a/buildSrc/src/main/kotlin/autorender.publish.gradle.kts b/buildSrc/src/main/kotlin/autorender.publish.gradle.kts index b1bba25..ab1af19 100644 --- a/buildSrc/src/main/kotlin/autorender.publish.gradle.kts +++ b/buildSrc/src/main/kotlin/autorender.publish.gradle.kts @@ -44,7 +44,7 @@ configure { pom { name.set("AutoRender Public API") description.set("REST API for uploading, managing, and serving media assets. All endpoints\nrequire an API key via the x-api-key header or Authorization: Bearer .") - url.set("https://autorender.mintlify.app/") + url.set("https://autorender.io/docs") licenses { license {