Skip to content

Commit b1f8ffc

Browse files
refactor(client): deduplicate page response classes (#596)
feat(client): make pagination robust to missing data docs: add comments for page methods
1 parent 2534fc3 commit b1f8ffc

182 files changed

Lines changed: 13405 additions & 8616 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.

lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountHolderListPage.kt

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

33
package com.lithic.api.models
44

5-
import com.fasterxml.jackson.annotation.JsonAnyGetter
6-
import com.fasterxml.jackson.annotation.JsonAnySetter
7-
import com.fasterxml.jackson.annotation.JsonCreator
8-
import com.fasterxml.jackson.annotation.JsonProperty
9-
import com.lithic.api.core.ExcludeMissing
10-
import com.lithic.api.core.JsonField
11-
import com.lithic.api.core.JsonMissing
12-
import com.lithic.api.core.JsonValue
13-
import com.lithic.api.errors.LithicInvalidDataException
145
import com.lithic.api.services.blocking.AccountHolderService
15-
import java.util.Collections
166
import java.util.Objects
177
import java.util.Optional
188
import java.util.stream.Stream
@@ -24,14 +14,26 @@ class AccountHolderListPage
2414
private constructor(
2515
private val accountHoldersService: AccountHolderService,
2616
private val params: AccountHolderListParams,
27-
private val response: Response,
17+
private val response: AccountHolderListPageResponse,
2818
) {
2919

30-
fun response(): Response = response
20+
/** Returns the response that this page was parsed from. */
21+
fun response(): AccountHolderListPageResponse = response
3122

32-
fun data(): List<AccountHolder> = response().data()
23+
/**
24+
* Delegates to [AccountHolderListPageResponse], but gracefully handles missing data.
25+
*
26+
* @see [AccountHolderListPageResponse.data]
27+
*/
28+
fun data(): List<AccountHolder> =
29+
response._data().getOptional("data").getOrNull() ?: emptyList()
3330

34-
fun hasMore(): Boolean = response().hasMore()
31+
/**
32+
* Delegates to [AccountHolderListPageResponse], but gracefully handles missing data.
33+
*
34+
* @see [AccountHolderListPageResponse.hasMore]
35+
*/
36+
fun hasMore(): Optional<Boolean> = response._hasMore().getOptional("has_more")
3537

3638
override fun equals(other: Any?): Boolean {
3739
if (this === other) {
@@ -46,13 +48,9 @@ private constructor(
4648
override fun toString() =
4749
"AccountHolderListPage{accountHoldersService=$accountHoldersService, params=$params, response=$response}"
4850

49-
fun hasNextPage(): Boolean {
50-
return !data().isEmpty()
51-
}
51+
fun hasNextPage(): Boolean = data().isNotEmpty()
5252

53-
fun getNextPageParams(): Optional<AccountHolderListParams> {
54-
return Optional.empty()
55-
}
53+
fun getNextPageParams(): Optional<AccountHolderListParams> = Optional.empty()
5654

5755
fun getNextPage(): Optional<AccountHolderListPage> {
5856
return getNextPageParams().map { accountHoldersService.list(it) }
@@ -66,119 +64,10 @@ private constructor(
6664
fun of(
6765
accountHoldersService: AccountHolderService,
6866
params: AccountHolderListParams,
69-
response: Response,
67+
response: AccountHolderListPageResponse,
7068
) = AccountHolderListPage(accountHoldersService, params, response)
7169
}
7270

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

18473
override fun iterator(): Iterator<AccountHolder> = iterator {

lithic-java-core/src/main/kotlin/com/lithic/api/models/AccountHolderListPageAsync.kt

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

33
package com.lithic.api.models
44

5-
import com.fasterxml.jackson.annotation.JsonAnyGetter
6-
import com.fasterxml.jackson.annotation.JsonAnySetter
7-
import com.fasterxml.jackson.annotation.JsonCreator
8-
import com.fasterxml.jackson.annotation.JsonProperty
9-
import com.lithic.api.core.ExcludeMissing
10-
import com.lithic.api.core.JsonField
11-
import com.lithic.api.core.JsonMissing
12-
import com.lithic.api.core.JsonValue
13-
import com.lithic.api.errors.LithicInvalidDataException
145
import com.lithic.api.services.async.AccountHolderServiceAsync
15-
import java.util.Collections
166
import java.util.Objects
177
import java.util.Optional
188
import java.util.concurrent.CompletableFuture
@@ -25,14 +15,26 @@ class AccountHolderListPageAsync
2515
private constructor(
2616
private val accountHoldersService: AccountHolderServiceAsync,
2717
private val params: AccountHolderListParams,
28-
private val response: Response,
18+
private val response: AccountHolderListPageResponse,
2919
) {
3020

31-
fun response(): Response = response
21+
/** Returns the response that this page was parsed from. */
22+
fun response(): AccountHolderListPageResponse = response
3223

33-
fun data(): List<AccountHolder> = response().data()
24+
/**
25+
* Delegates to [AccountHolderListPageResponse], but gracefully handles missing data.
26+
*
27+
* @see [AccountHolderListPageResponse.data]
28+
*/
29+
fun data(): List<AccountHolder> =
30+
response._data().getOptional("data").getOrNull() ?: emptyList()
3431

35-
fun hasMore(): Boolean = response().hasMore()
32+
/**
33+
* Delegates to [AccountHolderListPageResponse], but gracefully handles missing data.
34+
*
35+
* @see [AccountHolderListPageResponse.hasMore]
36+
*/
37+
fun hasMore(): Optional<Boolean> = response._hasMore().getOptional("has_more")
3638

3739
override fun equals(other: Any?): Boolean {
3840
if (this === other) {
@@ -47,13 +49,9 @@ private constructor(
4749
override fun toString() =
4850
"AccountHolderListPageAsync{accountHoldersService=$accountHoldersService, params=$params, response=$response}"
4951

50-
fun hasNextPage(): Boolean {
51-
return !data().isEmpty()
52-
}
52+
fun hasNextPage(): Boolean = data().isNotEmpty()
5353

54-
fun getNextPageParams(): Optional<AccountHolderListParams> {
55-
return Optional.empty()
56-
}
54+
fun getNextPageParams(): Optional<AccountHolderListParams> = Optional.empty()
5755

5856
fun getNextPage(): CompletableFuture<Optional<AccountHolderListPageAsync>> {
5957
return getNextPageParams()
@@ -69,120 +67,10 @@ private constructor(
6967
fun of(
7068
accountHoldersService: AccountHolderServiceAsync,
7169
params: AccountHolderListParams,
72-
response: Response,
70+
response: AccountHolderListPageResponse,
7371
) = AccountHolderListPageAsync(accountHoldersService, params, response)
7472
}
7573

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

18876
fun forEach(action: Predicate<AccountHolder>, executor: Executor): CompletableFuture<Void> {

0 commit comments

Comments
 (0)