generated from GenomicDataInfrastructure/oss-project-template
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fa0697b
commit d1d8554
Showing
16 changed files
with
108,618 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
...a/io/github/genomicdatainfrastructure/discovery/services/BeaconFilteringTermsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// SPDX-FileCopyrightText: 2024 PNED G.I.E. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package io.github.genomicdatainfrastructure.discovery.services; | ||
|
||
import static java.util.Optional.ofNullable; | ||
import static java.util.stream.Collectors.toMap; | ||
|
||
import org.eclipse.microprofile.rest.client.inject.RestClient; | ||
import io.github.genomicdatainfrastructure.discovery.model.Facet; | ||
import io.github.genomicdatainfrastructure.discovery.model.FacetGroup; | ||
import io.github.genomicdatainfrastructure.discovery.model.ValueLabel; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.api.BeaconQueryApi; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconFilteringTermsResponse; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconFilteringTermsResponseContent; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconResource; | ||
import io.quarkus.cache.CacheResult; | ||
import jakarta.enterprise.context.ApplicationScoped; | ||
import java.util.List; | ||
import java.util.ArrayList; | ||
|
||
@ApplicationScoped | ||
public class BeaconFilteringTermsService { | ||
|
||
private static final String DEFAULT_SCOPE = "individual"; | ||
|
||
private final BeaconQueryApi beaconQueryApi; | ||
|
||
public BeaconFilteringTermsService( | ||
@RestClient BeaconQueryApi beaconQueryApi | ||
) { | ||
this.beaconQueryApi = beaconQueryApi; | ||
} | ||
|
||
@CacheResult(cacheName = "beacon-facet-group-cache") | ||
public FacetGroup listFilteringTerms(String authorization) { | ||
var filteringTerms = beaconQueryApi.listFilteringTerms(authorization); | ||
|
||
var nonNullFilteringTermsResponse = ofNullable(filteringTerms) | ||
.map(BeaconFilteringTermsResponse::getResponse) | ||
.filter(it -> it.getFilteringTerms() != null && it.getResources() != null) | ||
.orElseGet(BeaconFilteringTermsResponseContent::new); | ||
|
||
var facetsMappedByName = nonNullFilteringTermsResponse.getResources().stream() | ||
.filter(it -> it.getName() != null && !it.getName().isBlank()) | ||
.collect(toMap( | ||
BeaconResource::getName, | ||
it -> Facet.builder() | ||
.key(it.getId()) | ||
.label(it.getName()) | ||
.values(new ArrayList<>()) | ||
.build() | ||
)); | ||
|
||
nonNullFilteringTermsResponse.getFilteringTerms().stream() | ||
.filter(it -> it.getLabel() != null && !it.getLabel().isBlank()) | ||
.filter(it -> it.getId() != null && !it.getId().isBlank()) | ||
.filter(it -> it.getScopes() != null && it.getScopes().contains(DEFAULT_SCOPE)) | ||
.filter(it -> facetsMappedByName.containsKey(it.getType())) | ||
.forEach(filteringTerm -> { | ||
var facet = facetsMappedByName.get(filteringTerm.getType()); | ||
var values = facet.getValues(); | ||
values.add(ValueLabel.builder() | ||
.value(filteringTerm.getId()) | ||
.label(filteringTerm.getLabel()) | ||
.build()); | ||
}); | ||
|
||
return FacetGroup.builder() | ||
.key("beacon") | ||
.label("Data") | ||
.facets(List.copyOf(facetsMappedByName.values())) | ||
.build(); | ||
} | ||
} |
163 changes: 163 additions & 0 deletions
163
...o/github/genomicdatainfrastructure/discovery/services/BeaconIndividualsSearchService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
// SPDX-FileCopyrightText: 2024 PNED G.I.E. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package io.github.genomicdatainfrastructure.discovery.services; | ||
|
||
import static java.util.Optional.ofNullable; | ||
import static java.util.function.Predicate.not; | ||
import static java.util.stream.Collectors.toCollection; | ||
|
||
import org.eclipse.microprofile.rest.client.inject.RestClient; | ||
import io.github.genomicdatainfrastructure.discovery.model.DatasetSearchQuery; | ||
import io.github.genomicdatainfrastructure.discovery.model.DatasetSearchQueryFacet; | ||
import io.github.genomicdatainfrastructure.discovery.model.DatasetsSearchResponse; | ||
import io.github.genomicdatainfrastructure.discovery.model.FacetGroup; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.api.BeaconQueryApi; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconIndividualsRequest; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconIndividualsRequestMeta; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconIndividualsRequestQuery; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconIndividualsRequestQueryFilter; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconIndividualsRequestQueryPagination; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconIndividualsResponse; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconIndividualsResponseContent; | ||
import io.github.genomicdatainfrastructure.discovery.remote.beacon.model.BeaconResultSet; | ||
import io.github.genomicdatainfrastructure.discovery.remote.keycloak.api.KeycloakQueryApi; | ||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.inject.Inject; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
|
||
@ApplicationScoped | ||
public class BeaconIndividualsSearchService { | ||
|
||
private static final String BEACON_FACET_GROUP = "beacon"; | ||
private static final String BEACON_IDP_ALIAS = "LSAAI"; | ||
private static final String BEARER_PATTERN = "Bearer %s"; | ||
private static final String BEACON_DATASET_TYPE = "dataset"; | ||
private static final String CKAN_FACET_GROUP = "ckan"; | ||
private static final String CKAN_IDENTIFIER_FIELD = "identifier"; | ||
private static final String SCOPE = "individual"; | ||
private static final String INCLUDE_RESULTSET_RESPONSES = "HIT"; | ||
private static final String REQUESTED_GRANULARITY = "count"; | ||
|
||
private final BeaconQueryApi beaconQueryApi; | ||
private final KeycloakQueryApi keycloakQueryApi; | ||
private final DatasetsSearchService datasetsSearchService; | ||
private final BeaconFilteringTermsService beaconFilteringTermsService; | ||
|
||
@Inject | ||
public BeaconIndividualsSearchService( | ||
@RestClient BeaconQueryApi beaconQueryApi, | ||
@RestClient KeycloakQueryApi keycloakQueryApi, | ||
DatasetsSearchService datasetsSearchService, | ||
BeaconFilteringTermsService beaconFilteringTermsService | ||
) { | ||
this.beaconQueryApi = beaconQueryApi; | ||
this.keycloakQueryApi = keycloakQueryApi; | ||
this.datasetsSearchService = datasetsSearchService; | ||
this.beaconFilteringTermsService = beaconFilteringTermsService; | ||
} | ||
|
||
public DatasetsSearchResponse search(DatasetSearchQuery query, String accessToken) { | ||
if (accessToken == null) { | ||
return datasetsSearchService.search(query, accessToken); | ||
} | ||
var beaconAuthorization = retrieveAuthorization(accessToken); | ||
var beaconResponse = queryOnBeacon(beaconAuthorization, query); | ||
var enhancedQuery = enhanceQueryFacets(query, beaconResponse); | ||
var datasetsReponse = datasetsSearchService.search(enhancedQuery, accessToken); | ||
return enhanceDatasetsResponse(beaconAuthorization, datasetsReponse, beaconResponse); | ||
} | ||
|
||
private String retrieveAuthorization(String accessToken) { | ||
var keycloakAuthorization = BEARER_PATTERN.formatted(accessToken); | ||
var response = keycloakQueryApi.retriveIdpTokens(BEACON_IDP_ALIAS, keycloakAuthorization); | ||
return BEARER_PATTERN.formatted(response.getAccessToken()); | ||
} | ||
|
||
private List<BeaconResultSet> queryOnBeacon( | ||
String beaconAuthorization, | ||
DatasetSearchQuery query | ||
) { | ||
var beaconFilters = ofNullable(query.getFacets()).orElseGet(List::of) | ||
.stream() | ||
.filter(it -> BEACON_FACET_GROUP.equals(it.getFacetGroup())) | ||
.map(DatasetSearchQueryFacet::getValue) | ||
.filter(not(String::isBlank)) | ||
.map(it -> BeaconIndividualsRequestQueryFilter.builder() | ||
.id(it) | ||
.scope(SCOPE) | ||
.build()) | ||
.toList(); | ||
|
||
var beaconQuery = BeaconIndividualsRequest.builder() | ||
.meta(new BeaconIndividualsRequestMeta()) | ||
.query(BeaconIndividualsRequestQuery.builder() | ||
.includeResultsetResponses(INCLUDE_RESULTSET_RESPONSES) | ||
.requestedGranularity(REQUESTED_GRANULARITY) | ||
.testMode(false) | ||
.pagination(new BeaconIndividualsRequestQueryPagination()) | ||
.filters(beaconFilters) | ||
.build()) | ||
.build(); | ||
|
||
var response = beaconQueryApi.listIndividuals(beaconAuthorization, beaconQuery); | ||
|
||
return ofNullable(response) | ||
.map(BeaconIndividualsResponse::getResponse) | ||
.map(BeaconIndividualsResponseContent::getResultSets) | ||
.orElseGet(List::of) | ||
.stream() | ||
.filter(it -> BEACON_DATASET_TYPE.equals(it.getSetType()) && | ||
it.getResultsCount() > 0 | ||
) | ||
.toList(); | ||
} | ||
|
||
private DatasetSearchQuery enhanceQueryFacets( | ||
DatasetSearchQuery query, | ||
List<BeaconResultSet> resultSets | ||
) { | ||
var enhancedFacets = resultSets.stream() | ||
.map(BeaconResultSet::getId) | ||
.map(it -> DatasetSearchQueryFacet.builder() | ||
.facetGroup(CKAN_FACET_GROUP) | ||
.facet(CKAN_IDENTIFIER_FIELD) | ||
.value(it) | ||
.build()) | ||
.collect(toCollection(ArrayList::new)); | ||
|
||
if (query.getFacets() != null) { | ||
enhancedFacets.addAll(query.getFacets()); | ||
} | ||
|
||
return query.toBuilder() | ||
.facets(enhancedFacets) | ||
.build(); | ||
} | ||
|
||
private DatasetsSearchResponse enhanceDatasetsResponse( | ||
String beaconAuthorization, | ||
DatasetsSearchResponse datasetsReponse, | ||
List<BeaconResultSet> resultSets | ||
) { | ||
var facetGroupCount = new HashMap<String, Integer>(); | ||
facetGroupCount.put("beacon", resultSets.size()); | ||
if (datasetsReponse.getFacetGroupCount() != null) { | ||
facetGroupCount.putAll(datasetsReponse.getFacetGroupCount()); | ||
} | ||
|
||
var facetGroups = new ArrayList<FacetGroup>(); | ||
facetGroups.add(beaconFilteringTermsService.listFilteringTerms(beaconAuthorization)); | ||
if (datasetsReponse.getFacetGroups() != null) { | ||
facetGroups.addAll(datasetsReponse.getFacetGroups()); | ||
} | ||
|
||
return datasetsReponse.toBuilder() | ||
.facetGroupCount(facetGroupCount) | ||
.facetGroups(facetGroups) | ||
.build(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.