Skip to content

Commit 7647787

Browse files
committed
Support derive endpoint as a fallback
1 parent 26844dc commit 7647787

File tree

4 files changed

+48
-4
lines changed

4 files changed

+48
-4
lines changed

access-grant/src/main/java/com/inrupt/client/accessgrant/AccessGrantClient.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,13 @@ public <T extends AccessCredential> CompletionStage<CredentialResult<T>> query(f
371371
}
372372

373373
return v1Metadata().thenCompose(metadata -> {
374-
// TODO check that query endpoint is nonnull
374+
if (metadata.queryEndpoint == null) {
375+
LOGGER.debug("Query endpoint not supported. Falling back to derive endpoint.");
376+
return query(filter.getResource().orElse(null), filter.getFromAgent().orElse(null),
377+
filter.getToAgent().orElse(null),
378+
filter.getPurpose().map(Collections::singleton).orElseGet(Collections::emptySet), null, clazz)
379+
.thenApply(results -> processResults(results, filter));
380+
}
375381
final Request req = Request.newBuilder(filter.asURI(metadata.queryEndpoint)).GET().build();
376382
return client.send(req, Response.BodyHandlers.ofInputStream()).thenApply(response -> {
377383
try (final InputStream input = response.body()) {
@@ -393,6 +399,25 @@ public <T extends AccessCredential> CompletionStage<CredentialResult<T>> query(f
393399
});
394400
}
395401

402+
<T extends AccessCredential> CredentialResult<T> processResults(final List<T> items,
403+
final CredentialFilter<T> filter) {
404+
final int pageCount = Utils.ceilDiv(items.size(), filter.getPageSize());
405+
final int page = Math.max(pageCount, filter.getPage().map(Utils::convertPage).orElse(1));
406+
if (pageCount > 1) {
407+
final CredentialFilter<T> first = CredentialFilter.newBuilder(filter)
408+
.page(Utils.convertPage(1)).build(filter.getCredentialType());
409+
final CredentialFilter<T> last = CredentialFilter.newBuilder(filter)
410+
.page(Utils.convertPage(pageCount)).build(filter.getCredentialType());
411+
final CredentialFilter<T> prev = page > 1 ? CredentialFilter.newBuilder(filter)
412+
.page(Utils.convertPage(page - 1)).build(filter.getCredentialType()) : null;
413+
final CredentialFilter<T> next = page < pageCount - 1 ? CredentialFilter.newBuilder(filter)
414+
.page(Utils.convertPage(page + 1)).build(filter.getCredentialType()) : null;
415+
return new CredentialResult<>(items, first, prev, next, last);
416+
} else {
417+
return new CredentialResult<>(items, null, null, null, null);
418+
}
419+
}
420+
396421
<T extends AccessCredential> Map<String, CredentialFilter<T>> processFilterResponseHeaders(final Headers headers,
397422
final CredentialFilter<T> filter) {
398423
final Map<String, CredentialFilter<T>> links = new HashMap<>();

access-grant/src/main/java/com/inrupt/client/accessgrant/Utils.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,25 @@ public static List<Map<String, Object>> getCredentialsFromPresentation(final Map
128128
return credentials;
129129
}
130130

131+
public static int convertPage(final String page) {
132+
try {
133+
final int p = Integer.parseInt(page);
134+
return Math.max(1, p);
135+
} catch (final IllegalArgumentException ex) {
136+
// ignore invalid values
137+
}
138+
return 1;
139+
}
140+
141+
public static String convertPage(final int page) {
142+
return Integer.toString(page);
143+
}
144+
145+
// Math.ceilDiv is not available in Java 11. This is an equivalent.
146+
public static int ceilDiv(final int x, final int y) {
147+
return (x + y - 1) / y;
148+
}
149+
131150
private Utils() {
132151
// prevent instantiation
133152
}

access-grant/src/test/java/com/inrupt/client/accessgrant/AccessGrantClientTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,7 @@ void testQueryPageFilter() {
464464

465465
final URI resource = URI.create("https://storage.example/e973cc3d-5c28-4a10-98c5-e40079289358/a/b/c");
466466

467-
final CredentialFilter<AccessRequest> filter = CredentialFilter.newBuilder().page("1")
467+
final CredentialFilter<AccessRequest> filter = CredentialFilter.newBuilder().page("1").pageSize(5)
468468
.build(AccessRequest.class);
469469

470470
final CredentialResult<AccessRequest> results = client.query(filter).toCompletableFuture().join();

access-grant/src/test/java/com/inrupt/client/accessgrant/MockAccessGrantServer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ private void setupMocks() {
215215
.withStatus(401)
216216
.withHeader("WWW-Authenticate", "Bearer,DPoP algs=\"ES256\"")));
217217

218-
wireMockServer.stubFor(get(urlEqualTo("/query?type=SolidAccessRequest&pageSize=20&page=1"))
218+
wireMockServer.stubFor(get(urlEqualTo("/query?type=SolidAccessRequest&pageSize=5&page=1"))
219219
.atPriority(1)
220220
.withHeader("Authorization", containing("Bearer eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9."))
221221
.willReturn(aResponse()
@@ -226,7 +226,7 @@ private void setupMocks() {
226226
.withHeader("Link", "</query?type=SolidAccessRequest&page=3&pageSize=20>; rel=\"last\"")
227227
.withBody(getResource("/query_request_page_response.json", wireMockServer.baseUrl()))));
228228

229-
wireMockServer.stubFor(get(urlEqualTo("/query?type=SolidAccessRequest&pageSize=20&page=1"))
229+
wireMockServer.stubFor(get(urlEqualTo("/query?type=SolidAccessRequest&pageSize=5&page=1"))
230230
.atPriority(2)
231231
.willReturn(aResponse()
232232
.withStatus(401)

0 commit comments

Comments
 (0)