Skip to content

Commit f8d72bb

Browse files
test(pagination): sonarcube refactor
2 parents f2d3c04 + e39684d commit f8d72bb

20 files changed

Lines changed: 418 additions & 286 deletions

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ Core lib's Maven group ID is `io.apimatic`, and its artifact ID is `core`.
5454
| [`CoreApiException`](./src/main/java/io/apimatic/core/types/CoreApiException.java) | This is the base class for all exceptions that represent an error response from the server |
5555
| [`MultipartFileWrapper`](./src/main/java/io/apimatic/core/types/http/request/MultipartFileWrapper.java) | To wrap file and headers to be sent as part of a multipart request |
5656
| [`MultipartWrapper`](./src/main/java/io/apimatic/core/types/http/request/MultipartWrapper.java) | To wrap byteArray and headers to be sent as part of a multipart request |
57+
| [`PaginatedData`](./src/main/java/io/apimatic/core/types/pagination/PaginatedData.java) | To provide pagination functionality for both syncrounous and asyncrounous pagination types |
58+
| [`PageWrapper`](./src/main/java/io/apimatic/core/types/pagination/PageWrapper.java) | To wrap a single page along with its items and meta-data in the paginated data |
59+
| [`CursorPagination`](./src/main/java/io/apimatic/core/types/pagination/CursorPagination.java) | Provides cursor based pagination strategy |
60+
| [`LinkPagination`](./src/main/java/io/apimatic/core/types/pagination/LinkPagination.java) | Provides link based pagination strategy |
61+
| [`OffsetPagination`](./src/main/java/io/apimatic/core/types/pagination/OffsetPagination.java) | Provides offset based pagination strategy |
62+
| [`PagePagination`](./src/main/java/io/apimatic/core/types/pagination/PagePagination.java) | Provides page based pagination strategy |
5763
| [`CoreHelper`](./src/main/java/io/apimatic/core/utilities/CoreHelper.java) | This is a Helper class with commonly used utilities for the SDK |
5864
| [`DateHelper`](./src/main/java/io/apimatic/core/utilities/DateHelper.java) | This is a utility class for LocalDate operations |
5965
| [`LocalDateTimeHelper`](./src/main/java/io/apimatic/core/utilities/LocalDateTimeHelper.java) | This is a utility class for LocalDateTime operations |
@@ -75,6 +81,7 @@ Core lib's Maven group ID is `io.apimatic`, and its artifact ID is `core`.
7581
| [`RequestExecutor`](./src/main/java/io/apimatic/core/request/async/RequestExecutor.java) | A Request executor that executes request and returns the response asynchronously |
7682
| [`RequestSupplier`](./src/main/java/io/apimatic/core/request/async/RequestSupplier.java) | A Request Supplier that supplies the request |
7783
| [`TypeCombinator`](./src/main/java/io/apimatic/core/annotations/TypeCombinator.java) | This is a container of annotations for oneOf/anyOf cases |
84+
| [`PaginationStrategy`](./src/main/java/io/apimatic/core/types/pagination/PaginationStrategy.java) | Provides the functionality to apply pagination parameters and return new request |
7885

7986
## Links
8087

src/main/java/io/apimatic/core/ApiCall.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ public ResponseType execute() throws IOException, ExceptionType {
105105
Context context = globalConfig.getCompatibilityFactory()
106106
.createHttpContext(request, response);
107107

108-
return responseHandler.handle(context, endpointConfiguration, globalConfig, requestBuilder);
108+
return responseHandler.handle(context, endpointConfiguration, globalConfig);
109109
}
110110

111111
/**
@@ -116,12 +116,11 @@ public CompletableFuture<ResponseType> executeAsync() {
116116
return AsyncExecutor.makeHttpCallAsync(() -> requestBuilder.build(globalConfig),
117117
request -> globalConfig.getHttpClient()
118118
.executeAsync(request, endpointConfiguration),
119-
(request, response) -> {
120-
this.response = response;
119+
(req, res) -> {
120+
this.response = res;
121121
Context context = globalConfig.getCompatibilityFactory()
122-
.createHttpContext(request, response);
123-
return responseHandler.handle(context, endpointConfiguration, globalConfig,
124-
requestBuilder);
122+
.createHttpContext(req, res);
123+
return responseHandler.handle(context, endpointConfiguration, globalConfig);
125124
}, apiLogger);
126125
}
127126

src/main/java/io/apimatic/core/HttpRequest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -325,13 +325,13 @@ public static class Builder {
325325
private Parameter.Builder parameterBuilder = new Parameter.Builder();
326326

327327
/**
328-
* Update the request parameters using a setter.
328+
* Update the request parameters using a setter thats called via a JSON pointer.
329329
*
330330
* @param pointer A JSON pointer pointing to any request field.
331331
* @param setter A function that takes in an old value and returns a new value.
332332
* @return The updated instance of current request builder.
333333
*/
334-
public Builder updateByReference(String pointer, UnaryOperator<Object> setter) {
334+
public Builder updateParameterByJsonPointer(String pointer, UnaryOperator<Object> setter) {
335335
if (pointer == null) {
336336
return this;
337337
}
@@ -364,18 +364,18 @@ private void updateBodyParams(UnaryOperator<Object> setter, String point) {
364364
return;
365365
}
366366

367-
if (bodySerializer != null && point == "") {
367+
if (bodySerializer != null && "".equals(point)) {
368368
try {
369369
String serializedBody = bodySerializer.supply();
370370
String newSerializedBody = setter.apply(serializedBody).toString();
371371
bodySerializer = () -> newSerializedBody;
372-
} catch (IOException e) {
372+
} catch (Exception e) {
373373
// Empty block
374374
}
375375
return;
376376
}
377377

378-
if ((body instanceof String && point == "") || point == "") {
378+
if ((body instanceof String && "".equals(point)) || "".equals(point)) {
379379
body = setter.apply(body);
380380
return;
381381
}

src/main/java/io/apimatic/core/ResponseHandler.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,14 @@ private ResponseHandler(final Map<String, ErrorCase<ExceptionType>> localErrorCa
114114
* @param context Context which is made for endpoint.
115115
* @param config All endPoint level configuration.
116116
* @param globalConfig All apiCall level configuration.
117-
* @param requestBuilder The requestBuilder that can re create current API Call.
118117
*
119118
* @return An object of type ResponseType.
120119
* @throws IOException Signals that an I/O exception of some sort has
121120
* occurred.
122121
* @throws ExceptionType Represents error response from the server.
123122
*/
124123
public ResponseType handle(Context context, EndpointConfiguration config,
125-
GlobalConfiguration globalConfig, HttpRequest.Builder requestBuilder)
126-
throws IOException, ExceptionType {
124+
GlobalConfiguration globalConfig) throws IOException, ExceptionType {
127125
if (globalConfig.getHttpCallback() != null) {
128126
// invoke the callback after response if its not null
129127
globalConfig.getHttpCallback().onAfterResponse(context);
@@ -140,8 +138,7 @@ public ResponseType handle(Context context, EndpointConfiguration config,
140138
// handle errors defined at the API level
141139
validateResponse(context);
142140

143-
Object result = convertResponse(context.getResponse(), requestBuilder, config,
144-
globalConfig);
141+
Object result = convertResponse(context.getResponse(), config, globalConfig);
145142

146143
if (responseClassType == ResponseClassType.API_RESPONSE
147144
|| responseClassType == ResponseClassType.DYNAMIC_API_RESPONSE) {
@@ -161,8 +158,8 @@ private ResponseType applyContextInitializer(Context httpContext,
161158
return (ResponseType) result;
162159
}
163160

164-
private Object convertResponse(Response response, HttpRequest.Builder requestBuilder,
165-
EndpointConfiguration config, GlobalConfiguration globalConfig) throws IOException {
161+
private Object convertResponse(Response response, EndpointConfiguration config,
162+
GlobalConfiguration globalConfig) throws IOException {
166163
if (responseClassType == ResponseClassType.DYNAMIC_RESPONSE
167164
|| responseClassType == ResponseClassType.DYNAMIC_API_RESPONSE) {
168165
return createDynamicResponse(response, globalConfig.getCompatibilityFactory());

src/main/java/io/apimatic/core/types/pagination/CheckedSupplier.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
import io.apimatic.core.types.CoreApiException;
66

7-
public interface CheckedSupplier<T, ExceptionType extends CoreApiException> {
7+
public interface CheckedSupplier<T, E extends CoreApiException> {
88

99
@SuppressWarnings("unchecked")
10-
public static <T, E extends CoreApiException> CheckedSupplier<T, E> CreateError(
10+
public static <T, E extends CoreApiException> CheckedSupplier<T, E> createError(
1111
Throwable exception) {
1212
if (exception instanceof IOException) {
1313
return new CheckedSupplier<T, E>()
@@ -33,7 +33,7 @@ public T get() throws E, IOException {
3333

3434
}
3535

36-
public static <T, E extends CoreApiException> CheckedSupplier<T, E> Create(T item) {
36+
public static <T, E extends CoreApiException> CheckedSupplier<T, E> create(T item) {
3737
return new CheckedSupplier<T, E>()
3838
{
3939
@Override
@@ -43,5 +43,5 @@ public T get() throws E, IOException {
4343
};
4444
}
4545

46-
T get() throws ExceptionType, IOException;
46+
T get() throws E, IOException;
4747
}

src/main/java/io/apimatic/core/types/pagination/CursorPagination.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.apimatic.core.types.pagination;
22

3+
import java.util.concurrent.atomic.AtomicBoolean;
4+
35
import io.apimatic.core.HttpRequest.Builder;
46
import io.apimatic.core.utilities.CoreHelper;
57
import io.apimatic.coreinterfaces.http.response.Response;
@@ -22,13 +24,13 @@ public CursorPagination(final String output, final String input) {
2224
public Builder apply(PaginatedData<?, ?, ?, ?> paginatedData) {
2325
Response response = paginatedData.getResponse();
2426
Builder reqBuilder = paginatedData.getRequestBuilder();
25-
final boolean[] isUpdated = {false};
27+
AtomicBoolean isUpdated = new AtomicBoolean(false);
2628

27-
reqBuilder.updateByReference(input, old -> {
29+
reqBuilder.updateParameterByJsonPointer(input, old -> {
2830

2931
if (response == null) {
3032
currentRequestCursor = (String) old;
31-
isUpdated[0] = true;
33+
isUpdated.set(true);
3234
return old;
3335
}
3436

@@ -39,15 +41,15 @@ public Builder apply(PaginatedData<?, ?, ?, ?> paginatedData) {
3941
}
4042

4143
currentRequestCursor = cursorValue;
42-
isUpdated[0] = true;
44+
isUpdated.set(true);
4345
return cursorValue;
4446
});
4547

46-
if (!isUpdated[0] && response == null) {
48+
if (!isUpdated.get() && response == null) {
4749
return reqBuilder;
4850
}
4951

50-
return isUpdated[0] ? reqBuilder : null;
52+
return isUpdated.get() ? reqBuilder : null;
5153
}
5254

5355
@Override

src/main/java/io/apimatic/core/types/pagination/OffsetPagination.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.apimatic.core.types.pagination;
22

3+
import java.util.concurrent.atomic.AtomicBoolean;
4+
35
import io.apimatic.core.HttpRequest.Builder;
46
import io.apimatic.coreinterfaces.http.response.Response;
57

@@ -18,28 +20,28 @@ public OffsetPagination(final String input) {
1820
public Builder apply(PaginatedData<?, ?, ?, ?> paginatedData) {
1921
Response response = paginatedData.getResponse();
2022
Builder reqBuilder = paginatedData.getRequestBuilder();
21-
final boolean[] isUpdated = {false};
23+
AtomicBoolean isUpdated = new AtomicBoolean(false);
2224

23-
reqBuilder.updateByReference(input, old -> {
25+
reqBuilder.updateParameterByJsonPointer(input, old -> {
2426
int oldValue = Integer.parseInt("" + old);
2527

2628
if (response == null) {
2729
currentRequestOffset = oldValue;
28-
isUpdated[0] = true;
30+
isUpdated.set(true);
2931
return old;
3032
}
3133

3234
int newValue = oldValue + paginatedData.getPageSize();
3335
currentRequestOffset = newValue;
34-
isUpdated[0] = true;
36+
isUpdated.set(true);
3537
return newValue;
3638
});
3739

38-
if (!isUpdated[0] && response == null) {
40+
if (!isUpdated.get() && response == null) {
3941
return reqBuilder;
4042
}
4143

42-
return isUpdated[0] ? reqBuilder : null;
44+
return isUpdated.get() ? reqBuilder : null;
4345
}
4446

4547
@Override

src/main/java/io/apimatic/core/types/pagination/PagePagination.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.apimatic.core.types.pagination;
22

3+
import java.util.concurrent.atomic.AtomicBoolean;
4+
35
import io.apimatic.core.HttpRequest.Builder;
46
import io.apimatic.coreinterfaces.http.response.Response;
57

@@ -18,28 +20,28 @@ public PagePagination(final String input) {
1820
public Builder apply(PaginatedData<?, ?, ?, ?> paginatedData) {
1921
Response response = paginatedData.getResponse();
2022
Builder reqBuilder = paginatedData.getRequestBuilder();
21-
final boolean[] isUpdated = {false};
23+
AtomicBoolean isUpdated = new AtomicBoolean(false);
2224

23-
reqBuilder.updateByReference(input, old -> {
25+
reqBuilder.updateParameterByJsonPointer(input, old -> {
2426
int oldValue = Integer.parseInt("" + old);
2527

2628
if (response == null) {
2729
currentRequestPageNumber = oldValue;
28-
isUpdated[0] = true;
30+
isUpdated.set(true);
2931
return old;
3032
}
3133

3234
int newValue = oldValue + 1;
3335
currentRequestPageNumber = newValue;
34-
isUpdated[0] = true;
36+
isUpdated.set(true);
3537
return newValue;
3638
});
3739

38-
if (!isUpdated[0] && response == null) {
40+
if (!isUpdated.get() && response == null) {
3941
return reqBuilder;
4042
}
4143

42-
return isUpdated[0] ? reqBuilder : null;
44+
return isUpdated.get() ? reqBuilder : null;
4345
}
4446

4547
@Override

src/main/java/io/apimatic/core/types/pagination/PaginatedData.java

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public class PaginatedData<I, P, R, E extends CoreApiException> {
2424
private final List<CheckedSupplier<I, E>> items = new ArrayList<>();
2525
private CheckedSupplier<P, E> page = null;
2626
private ApiCall<R, E> apiCall;
27+
private PaginationStrategy lockedStrategy;
28+
private boolean canLockStrategy = false;
2729
private boolean dataClosed = false;
2830

2931
public PaginatedData(final ApiCall<R, E> apiCall,
@@ -79,6 +81,7 @@ public <T> T getPage(Function<CheckedSupplier<P, E>, T> pageSupplier) {
7981
/**
8082
* @return An Iterator of items of type T
8183
*/
84+
8285
public <T> Iterator<T> items(Function<CheckedSupplier<I, E>, T> itemSupplier) {
8386
PaginatedData<I, P, R, E> paginatedData = new PaginatedData<>(
8487
firstApiCall, pageCreator, itemsCreator, strategies);
@@ -107,6 +110,7 @@ public T next() {
107110
/**
108111
* @return An Iterator of pages of type T
109112
*/
113+
110114
public <T> Iterator<T> pages(Function<CheckedSupplier<P, E>, T> pageSupplier) {
111115
PaginatedData<I, P, R, E> paginatedData = new PaginatedData<>(
112116
firstApiCall, pageCreator, itemsCreator, strategies);
@@ -134,13 +138,17 @@ public T next() {
134138

135139
};
136140
}
141+
142+
public PaginatedData<I, P, R, E> copy() {
143+
return new PaginatedData<>(firstApiCall, pageCreator, itemsCreator, strategies);
144+
}
137145

138146
public CompletableFuture<Boolean> fetchNextPageAsync() {
139147
if (dataClosed) {
140148
return CompletableFuture.completedFuture(false);
141149
}
142150

143-
for (PaginationStrategy strategy : strategies) {
151+
for (PaginationStrategy strategy : getStrategies()) {
144152
HttpRequest.Builder requestBuilder = strategy.apply(this);
145153
if (requestBuilder == null) continue;
146154

@@ -161,7 +169,7 @@ private boolean fetchNextPage() {
161169
return false;
162170
}
163171

164-
for (PaginationStrategy strategy : strategies) {
172+
for (PaginationStrategy strategy : getStrategies()) {
165173

166174
HttpRequest.Builder requestBuilder = strategy.apply(this);
167175
if (requestBuilder == null) {
@@ -182,7 +190,16 @@ private boolean fetchNextPage() {
182190
return false;
183191
}
184192

193+
private PaginationStrategy[] getStrategies() {
194+
if (lockedStrategy == null) {
195+
return strategies;
196+
}
197+
198+
return new PaginationStrategy[] { lockedStrategy };
199+
}
200+
185201
private boolean updateWith(ApiCall<R, E> apiCall, R pageUnWrapped, PaginationStrategy strategy) {
202+
186203
itemIndex = 0;
187204
this.items.clear();
188205
this.page = null;
@@ -199,17 +216,23 @@ private boolean updateWith(ApiCall<R, E> apiCall, R pageUnWrapped, PaginationStr
199216
this.apiCall = apiCall;
200217
PageWrapper<I, R> pageWrapper = PageWrapper.create(apiCall.getResponse(), pageUnWrapped, itemsUnWrapped);
201218
strategy.addMetaData(pageWrapper);
202-
this.page = CheckedSupplier.Create(pageCreator.apply(pageWrapper));
203-
itemsUnWrapped.forEach(i -> items.add(CheckedSupplier.Create(i)));
219+
this.page = CheckedSupplier.create(pageCreator.apply(pageWrapper));
220+
itemsUnWrapped.forEach(i -> items.add(CheckedSupplier.create(i)));
221+
222+
if (canLockStrategy) {
223+
lockedStrategy = strategy;
224+
} else {
225+
canLockStrategy = true;
226+
}
204227

205228
return true;
206229
}
207230

208231
private boolean updateAsFailed(Throwable exp) {
209-
page = CheckedSupplier.CreateError(exp);
232+
page = CheckedSupplier.createError(exp);
210233
itemIndex = 0;
211234
items.clear();
212-
items.add(CheckedSupplier.CreateError(exp));
235+
items.add(CheckedSupplier.createError(exp));
213236
dataClosed = true;
214237

215238
return true;

0 commit comments

Comments
 (0)