Skip to content

Commit 445e30e

Browse files
refactor(client): deduplicate page response classes
feat(client): make pagination robust to missing data docs: add comments for page methods
1 parent a2f69b5 commit 445e30e

96 files changed

Lines changed: 5918 additions & 3773 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

braintrust-java-core/src/main/kotlin/com/braintrustdata/api/models/AclListPage.kt

Lines changed: 18 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,7 @@
22

33
package com.braintrustdata.api.models
44

5-
import com.braintrustdata.api.core.ExcludeMissing
6-
import com.braintrustdata.api.core.JsonField
7-
import com.braintrustdata.api.core.JsonMissing
8-
import com.braintrustdata.api.core.JsonValue
9-
import com.braintrustdata.api.errors.BraintrustInvalidDataException
105
import com.braintrustdata.api.services.blocking.AclService
11-
import com.fasterxml.jackson.annotation.JsonAnyGetter
12-
import com.fasterxml.jackson.annotation.JsonAnySetter
13-
import com.fasterxml.jackson.annotation.JsonCreator
14-
import com.fasterxml.jackson.annotation.JsonProperty
15-
import java.util.Collections
166
import java.util.Objects
177
import java.util.Optional
188
import java.util.stream.Stream
@@ -27,12 +17,18 @@ class AclListPage
2717
private constructor(
2818
private val aclsService: AclService,
2919
private val params: AclListParams,
30-
private val response: Response,
20+
private val response: AclListPageResponse,
3121
) {
3222

33-
fun response(): Response = response
23+
/** Returns the response that this page was parsed from. */
24+
fun response(): AclListPageResponse = response
3425

35-
fun objects(): List<Acl> = response().objects()
26+
/**
27+
* Delegates to [AclListPageResponse], but gracefully handles missing data.
28+
*
29+
* @see [AclListPageResponse.objects]
30+
*/
31+
fun objects(): List<Acl> = response._objects().getOptional("objects").getOrNull() ?: emptyList()
3632

3733
override fun equals(other: Any?): Boolean {
3834
if (this === other) {
@@ -47,20 +43,20 @@ private constructor(
4743
override fun toString() =
4844
"AclListPage{aclsService=$aclsService, params=$params, response=$response}"
4945

50-
fun hasNextPage(): Boolean {
51-
return !objects().isEmpty()
52-
}
46+
fun hasNextPage(): Boolean = objects().isNotEmpty()
5347

5448
fun getNextPageParams(): Optional<AclListParams> {
5549
if (!hasNextPage()) {
5650
return Optional.empty()
5751
}
5852

59-
return if (params.endingBefore().isPresent) {
60-
Optional.of(params.toBuilder().endingBefore(objects().first().id()).build())
61-
} else {
62-
Optional.of(params.toBuilder().startingAfter(objects().last().id()).build())
63-
}
53+
return Optional.of(
54+
if (params.endingBefore().isPresent) {
55+
params.toBuilder().endingBefore(objects().first()._id().getOptional("id")).build()
56+
} else {
57+
params.toBuilder().startingAfter(objects().last()._id().getOptional("id")).build()
58+
}
59+
)
6460
}
6561

6662
fun getNextPage(): Optional<AclListPage> {
@@ -72,103 +68,10 @@ private constructor(
7268
companion object {
7369

7470
@JvmStatic
75-
fun of(aclsService: AclService, params: AclListParams, response: Response) =
71+
fun of(aclsService: AclService, params: AclListParams, response: AclListPageResponse) =
7672
AclListPage(aclsService, params, response)
7773
}
7874

79-
class Response(
80-
private val objects: JsonField<List<Acl>>,
81-
private val additionalProperties: MutableMap<String, JsonValue>,
82-
) {
83-
84-
@JsonCreator
85-
private constructor(
86-
@JsonProperty("objects") objects: JsonField<List<Acl>> = JsonMissing.of()
87-
) : this(objects, mutableMapOf())
88-
89-
fun objects(): List<Acl> = objects.getOptional("objects").getOrNull() ?: listOf()
90-
91-
@JsonProperty("objects")
92-
fun _objects(): Optional<JsonField<List<Acl>>> = Optional.ofNullable(objects)
93-
94-
@JsonAnySetter
95-
private fun putAdditionalProperty(key: String, value: JsonValue) {
96-
additionalProperties.put(key, value)
97-
}
98-
99-
@JsonAnyGetter
100-
@ExcludeMissing
101-
fun _additionalProperties(): Map<String, JsonValue> =
102-
Collections.unmodifiableMap(additionalProperties)
103-
104-
private var validated: Boolean = false
105-
106-
fun validate(): Response = apply {
107-
if (validated) {
108-
return@apply
109-
}
110-
111-
objects().map { it.validate() }
112-
validated = true
113-
}
114-
115-
fun isValid(): Boolean =
116-
try {
117-
validate()
118-
true
119-
} catch (e: BraintrustInvalidDataException) {
120-
false
121-
}
122-
123-
fun toBuilder() = Builder().from(this)
124-
125-
override fun equals(other: Any?): Boolean {
126-
if (this === other) {
127-
return true
128-
}
129-
130-
return /* spotless:off */ other is Response && objects == other.objects && additionalProperties == other.additionalProperties /* spotless:on */
131-
}
132-
133-
override fun hashCode(): Int = /* spotless:off */ Objects.hash(objects, additionalProperties) /* spotless:on */
134-
135-
override fun toString() =
136-
"Response{objects=$objects, additionalProperties=$additionalProperties}"
137-
138-
companion object {
139-
140-
/** Returns a mutable builder for constructing an instance of [AclListPage]. */
141-
@JvmStatic fun builder() = Builder()
142-
}
143-
144-
class Builder {
145-
146-
private var objects: JsonField<List<Acl>> = JsonMissing.of()
147-
private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()
148-
149-
@JvmSynthetic
150-
internal fun from(page: Response) = apply {
151-
this.objects = page.objects
152-
this.additionalProperties.putAll(page.additionalProperties)
153-
}
154-
155-
fun objects(objects: List<Acl>) = objects(JsonField.of(objects))
156-
157-
fun objects(objects: JsonField<List<Acl>>) = apply { this.objects = objects }
158-
159-
fun putAdditionalProperty(key: String, value: JsonValue) = apply {
160-
this.additionalProperties.put(key, value)
161-
}
162-
163-
/**
164-
* Returns an immutable instance of [Response].
165-
*
166-
* Further updates to this [Builder] will not mutate the returned instance.
167-
*/
168-
fun build(): Response = Response(objects, additionalProperties.toMutableMap())
169-
}
170-
}
171-
17275
class AutoPager(private val firstPage: AclListPage) : Iterable<Acl> {
17376

17477
override fun iterator(): Iterator<Acl> = iterator {

braintrust-java-core/src/main/kotlin/com/braintrustdata/api/models/AclListPageAsync.kt

Lines changed: 18 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,7 @@
22

33
package com.braintrustdata.api.models
44

5-
import com.braintrustdata.api.core.ExcludeMissing
6-
import com.braintrustdata.api.core.JsonField
7-
import com.braintrustdata.api.core.JsonMissing
8-
import com.braintrustdata.api.core.JsonValue
9-
import com.braintrustdata.api.errors.BraintrustInvalidDataException
105
import com.braintrustdata.api.services.async.AclServiceAsync
11-
import com.fasterxml.jackson.annotation.JsonAnyGetter
12-
import com.fasterxml.jackson.annotation.JsonAnySetter
13-
import com.fasterxml.jackson.annotation.JsonCreator
14-
import com.fasterxml.jackson.annotation.JsonProperty
15-
import java.util.Collections
166
import java.util.Objects
177
import java.util.Optional
188
import java.util.concurrent.CompletableFuture
@@ -28,12 +18,18 @@ class AclListPageAsync
2818
private constructor(
2919
private val aclsService: AclServiceAsync,
3020
private val params: AclListParams,
31-
private val response: Response,
21+
private val response: AclListPageResponse,
3222
) {
3323

34-
fun response(): Response = response
24+
/** Returns the response that this page was parsed from. */
25+
fun response(): AclListPageResponse = response
3526

36-
fun objects(): List<Acl> = response().objects()
27+
/**
28+
* Delegates to [AclListPageResponse], but gracefully handles missing data.
29+
*
30+
* @see [AclListPageResponse.objects]
31+
*/
32+
fun objects(): List<Acl> = response._objects().getOptional("objects").getOrNull() ?: emptyList()
3733

3834
override fun equals(other: Any?): Boolean {
3935
if (this === other) {
@@ -48,20 +44,20 @@ private constructor(
4844
override fun toString() =
4945
"AclListPageAsync{aclsService=$aclsService, params=$params, response=$response}"
5046

51-
fun hasNextPage(): Boolean {
52-
return !objects().isEmpty()
53-
}
47+
fun hasNextPage(): Boolean = objects().isNotEmpty()
5448

5549
fun getNextPageParams(): Optional<AclListParams> {
5650
if (!hasNextPage()) {
5751
return Optional.empty()
5852
}
5953

60-
return if (params.endingBefore().isPresent) {
61-
Optional.of(params.toBuilder().endingBefore(objects().first().id()).build())
62-
} else {
63-
Optional.of(params.toBuilder().startingAfter(objects().last().id()).build())
64-
}
54+
return Optional.of(
55+
if (params.endingBefore().isPresent) {
56+
params.toBuilder().endingBefore(objects().first()._id().getOptional("id")).build()
57+
} else {
58+
params.toBuilder().startingAfter(objects().last()._id().getOptional("id")).build()
59+
}
60+
)
6561
}
6662

6763
fun getNextPage(): CompletableFuture<Optional<AclListPageAsync>> {
@@ -75,103 +71,10 @@ private constructor(
7571
companion object {
7672

7773
@JvmStatic
78-
fun of(aclsService: AclServiceAsync, params: AclListParams, response: Response) =
74+
fun of(aclsService: AclServiceAsync, params: AclListParams, response: AclListPageResponse) =
7975
AclListPageAsync(aclsService, params, response)
8076
}
8177

82-
class Response(
83-
private val objects: JsonField<List<Acl>>,
84-
private val additionalProperties: MutableMap<String, JsonValue>,
85-
) {
86-
87-
@JsonCreator
88-
private constructor(
89-
@JsonProperty("objects") objects: JsonField<List<Acl>> = JsonMissing.of()
90-
) : this(objects, mutableMapOf())
91-
92-
fun objects(): List<Acl> = objects.getOptional("objects").getOrNull() ?: listOf()
93-
94-
@JsonProperty("objects")
95-
fun _objects(): Optional<JsonField<List<Acl>>> = Optional.ofNullable(objects)
96-
97-
@JsonAnySetter
98-
private fun putAdditionalProperty(key: String, value: JsonValue) {
99-
additionalProperties.put(key, value)
100-
}
101-
102-
@JsonAnyGetter
103-
@ExcludeMissing
104-
fun _additionalProperties(): Map<String, JsonValue> =
105-
Collections.unmodifiableMap(additionalProperties)
106-
107-
private var validated: Boolean = false
108-
109-
fun validate(): Response = apply {
110-
if (validated) {
111-
return@apply
112-
}
113-
114-
objects().map { it.validate() }
115-
validated = true
116-
}
117-
118-
fun isValid(): Boolean =
119-
try {
120-
validate()
121-
true
122-
} catch (e: BraintrustInvalidDataException) {
123-
false
124-
}
125-
126-
fun toBuilder() = Builder().from(this)
127-
128-
override fun equals(other: Any?): Boolean {
129-
if (this === other) {
130-
return true
131-
}
132-
133-
return /* spotless:off */ other is Response && objects == other.objects && additionalProperties == other.additionalProperties /* spotless:on */
134-
}
135-
136-
override fun hashCode(): Int = /* spotless:off */ Objects.hash(objects, additionalProperties) /* spotless:on */
137-
138-
override fun toString() =
139-
"Response{objects=$objects, additionalProperties=$additionalProperties}"
140-
141-
companion object {
142-
143-
/** Returns a mutable builder for constructing an instance of [AclListPageAsync]. */
144-
@JvmStatic fun builder() = Builder()
145-
}
146-
147-
class Builder {
148-
149-
private var objects: JsonField<List<Acl>> = JsonMissing.of()
150-
private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()
151-
152-
@JvmSynthetic
153-
internal fun from(page: Response) = apply {
154-
this.objects = page.objects
155-
this.additionalProperties.putAll(page.additionalProperties)
156-
}
157-
158-
fun objects(objects: List<Acl>) = objects(JsonField.of(objects))
159-
160-
fun objects(objects: JsonField<List<Acl>>) = apply { this.objects = objects }
161-
162-
fun putAdditionalProperty(key: String, value: JsonValue) = apply {
163-
this.additionalProperties.put(key, value)
164-
}
165-
166-
/**
167-
* Returns an immutable instance of [Response].
168-
*
169-
* Further updates to this [Builder] will not mutate the returned instance.
170-
*/
171-
fun build(): Response = Response(objects, additionalProperties.toMutableMap())
172-
}
173-
}
174-
17578
class AutoPager(private val firstPage: AclListPageAsync) {
17679

17780
fun forEach(action: Predicate<Acl>, executor: Executor): CompletableFuture<Void> {

0 commit comments

Comments
 (0)