Skip to content

Commit

Permalink
feat: add endpoint to retrieve list of facets
Browse files Browse the repository at this point in the history
  • Loading branch information
admy7 committed Sep 5, 2024
1 parent 73281f3 commit f9ebb7c
Show file tree
Hide file tree
Showing 10 changed files with 689 additions and 15 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.github.genomicdatainfrastructure.discovery.facets.application;

import io.github.genomicdatainfrastructure.discovery.facets.ports.IFacetBuilder;
import io.github.genomicdatainfrastructure.discovery.model.Facet;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Instance;
import jakarta.inject.Inject;
import lombok.RequiredArgsConstructor;

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RequiredArgsConstructor(onConstructor = @__(@Inject))
@ApplicationScoped
public class RetrieveFacetsQuery {

private final Instance<IFacetBuilder> facetsBuilders;

public List<Facet> execute(String accessToken) {
return facetsBuilders
.stream()
.map(facetBuilder -> facetBuilder.build(accessToken))
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.github.genomicdatainfrastructure.discovery.facets.infrastructure.beacon;

import io.github.genomicdatainfrastructure.discovery.datasets.infrastructure.beacon.auth.BeaconAuth;
import io.github.genomicdatainfrastructure.discovery.facets.ports.IFacetBuilder;
import io.github.genomicdatainfrastructure.discovery.model.Facet;
import io.github.genomicdatainfrastructure.discovery.services.BeaconFilteringTermsService;
import io.quarkus.arc.lookup.LookupIfProperty;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import java.util.List;

@ApplicationScoped
@LookupIfProperty(name = "sources.beacon", stringValue = "true")
public class BeaconFacetBuilder implements IFacetBuilder {

private final BeaconFilteringTermsService service;
private final BeaconAuth beaconAuth;

@Inject
public BeaconFacetBuilder(BeaconFilteringTermsService service, BeaconAuth beaconAuth) {
this.service = service;
this.beaconAuth = beaconAuth;
}

@Override
public List<Facet> build(String accessToken) {
var beaconAuthorization = beaconAuth.retrieveAuthorization(accessToken);
if (beaconAuthorization == null) {
return null;
}
return service.listFilteringTermList(beaconAuthorization);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package io.github.genomicdatainfrastructure.discovery.facets.infrastructure.ckan;

import io.github.genomicdatainfrastructure.discovery.facets.ports.IFacetBuilder;
import io.github.genomicdatainfrastructure.discovery.model.Facet;
import io.github.genomicdatainfrastructure.discovery.model.ValueLabel;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.api.CkanQueryApi;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.model.CkanFacet;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.model.PackagesSearchResult;
import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.rest.client.inject.RestClient;

import java.util.List;
import java.util.Map;

import static io.github.genomicdatainfrastructure.discovery.datasets.infrastructure.ckan.config.CkanConfiguration.CKAN_FACET_GROUP;
import static java.util.Optional.ofNullable;

@ApplicationScoped
public class CkanFacetBuilder implements IFacetBuilder {

private static final String SELECTED_FACETS_PATTERN = "[\"%s\"]";

private final CkanQueryApi ckanQueryApi;
private final String selectedFacets;

public CkanFacetBuilder(@RestClient CkanQueryApi ckanQueryApi,
@ConfigProperty(name = "datasets.filters") String datasetFiltersAsString) {
this.ckanQueryApi = ckanQueryApi;
this.selectedFacets = SELECTED_FACETS_PATTERN.formatted(String.join("\",\"",
datasetFiltersAsString.split(",")));
}

@Override
public List<Facet> build(String accessToken) {
var response = ckanQueryApi.packageSearch(
null,
null,
null,
null,
null,
selectedFacets,
accessToken
);

var nonNullSearchFacets = ofNullable(response.getResult())
.map(PackagesSearchResult::getSearchFacets)
.orElseGet(Map::of);

return facets(nonNullSearchFacets);
}

private List<Facet> facets(Map<String, CkanFacet> facets) {
return facets
.entrySet()
.stream()
.map(this::facet)
.toList();
}

private Facet facet(Map.Entry<String, CkanFacet> entry) {
var key = entry.getKey();
var facet = entry.getValue();

var values = ofNullable(facet.getItems())
.orElseGet(List::of)
.stream()
.map(value -> ValueLabel.builder()
.value(value.getName())
.label(value.getDisplayName())
.build()
)
.toList();

return Facet
.builder()
.facetGroup(CKAN_FACET_GROUP)
.key(key)
.label(facet.getTitle())
.values(values)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.github.genomicdatainfrastructure.discovery.facets.infrastructure.quarkus;

import io.github.genomicdatainfrastructure.discovery.api.SearchFacetsQueryApi;
import io.github.genomicdatainfrastructure.discovery.facets.application.RetrieveFacetsQuery;
import io.quarkus.oidc.runtime.OidcJwtCallerPrincipal;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.ws.rs.core.Response;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class FacetsController implements SearchFacetsQueryApi {

private final SecurityIdentity identity;
private final RetrieveFacetsQuery query;

@Override
public Response retrieveSearchFacets() {
var facets = query.execute(accessToken());
return Response.ok(facets).build();
}

private String accessToken() {
if (identity.isAnonymous()) {
return null;
}
var principal = (OidcJwtCallerPrincipal) identity.getPrincipal();
return principal.getRawToken();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.github.genomicdatainfrastructure.discovery.facets.ports;

import io.github.genomicdatainfrastructure.discovery.model.Facet;

import java.util.List;

public interface IFacetBuilder {

List<Facet> build(String accessToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ public FacetGroup listFilteringTerms(String authorization) {
.build();
}

@CacheResult(cacheName = "beacon-facets-cache")
public List<Facet> listFilteringTermList(String authorization) {
var filteringTermsResponse = retrieveNonNullFilteringTermsResponse(authorization);

var valuesGroupedByFacetId = groupValuesByFacetId(filteringTermsResponse);

var facetIdsMappedByName = mapFacetNamesByFacetId(filteringTermsResponse);

var facets = buildFacets(valuesGroupedByFacetId, facetIdsMappedByName);

return facets;
}

private BeaconFilteringTermsResponseContent retrieveNonNullFilteringTermsResponse(
String authorization
) {
Expand Down Expand Up @@ -116,6 +129,7 @@ private List<Facet> buildFacets(
return termsGroupedByType.entrySet().stream()
.filter(entry -> facetNamesMappedById.containsKey(entry.getKey()))
.map(entry -> Facet.builder()
.facetGroup(BEACON_FACET_GROUP)
.key(entry.getKey())
.label(facetNamesMappedById.get(entry.getKey()))
.values(entry.getValue())
Expand Down
21 changes: 21 additions & 0 deletions src/main/openapi/discovery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,24 @@ paths:
security:
- discovery_auth:
- read:datasets
/api/v1/search-facets:
get:
summary: Retrieves search facets for querying datasets
operationId: retrieve_search_facets
tags:
- "search-facets-query"
responses:
"200":
description: A list of search facets
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Facet"
security:
- discovery_auth:
- read:search-facets
components:
securitySchemes:
discovery_auth:
Expand Down Expand Up @@ -483,6 +501,9 @@ components:
title: Facets
Facet:
properties:
facetGroup:
type: string
title: Facet group
key:
type: string
title: Key
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package io.github.genomicdatainfrastructure.discovery.api;

import com.github.tomakehurst.wiremock.client.WireMock;
import io.github.genomicdatainfrastructure.discovery.BaseTest;
import io.quarkus.test.junit.QuarkusTest;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasSize;

@QuarkusTest
public class RetrieveFacetsTest extends BaseTest {

WireMock wireMock;

@Test
void retrieve_ckan_facets_when_not_authenticated() {
given()
.get("/api/v1/search-facets")
.then()
.statusCode(200)
.body("", hasSize(5))
.body("[0].facetGroup", Matchers.equalTo("ckan"))
.body("[0].key", Matchers.equalTo("tags"))
.body("[0].label", Matchers.equalTo("Keywords"))
.body("[0].values", hasSize(16))

.body("[1].facetGroup", Matchers.equalTo("ckan"))
.body("[1].key", Matchers.equalTo("organization"))
.body("[1].label", Matchers.equalTo("Publishers"))
.body("[1].values", hasSize(7));
}

@Test
void retrieve_all_facets_when_authenticated() {
given()
.auth()
.oauth2(getAccessToken("alice"))
.get("/api/v1/search-facets")
.then()
.statusCode(200)
.body("", hasSize(11));
}
}
Loading

0 comments on commit f9ebb7c

Please sign in to comment.