From 3148f7713babd84ef267e7bdc7c7189db11c2dc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Youn=C3=A8s=20Adem?= <63497031+admy7@users.noreply.github.com> Date: Fri, 6 Sep 2024 09:38:46 +0200 Subject: [PATCH] feat: add endpoint to retrieve list of facets (#112) --- .../application/RetrieveFacetsQuery.java | 33 ++ .../beacon/BeaconFacetBuilder.java | 38 +++ .../infrastructure/ckan/CkanFacetBuilder.java | 87 +++++ .../quarkus/FacetsController.java | 33 ++ .../discovery/facets/ports/IFacetBuilder.java | 14 + .../services/BeaconFilteringTermsService.java | 14 + src/main/openapi/discovery.yaml | 21 ++ .../discovery/api/RetrieveFacetsTest.java | 53 +++ .../facets/RetrieveFacetsQueryTest.java | 121 +++++++ .../mappings/package_search_facets.json | 322 +++++++++++++++++- 10 files changed, 721 insertions(+), 15 deletions(-) create mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/facets/application/RetrieveFacetsQuery.java create mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/beacon/BeaconFacetBuilder.java create mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/ckan/CkanFacetBuilder.java create mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/quarkus/FacetsController.java create mode 100644 src/main/java/io/github/genomicdatainfrastructure/discovery/facets/ports/IFacetBuilder.java create mode 100644 src/test/java/io/github/genomicdatainfrastructure/discovery/api/RetrieveFacetsTest.java create mode 100644 src/test/java/io/github/genomicdatainfrastructure/discovery/facets/RetrieveFacetsQueryTest.java diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/application/RetrieveFacetsQuery.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/application/RetrieveFacetsQuery.java new file mode 100644 index 0000000..ad7e77d --- /dev/null +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/application/RetrieveFacetsQuery.java @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +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 facetsBuilders; + + public List execute(String accessToken) { + return facetsBuilders + .stream() + .map(facetBuilder -> facetBuilder.build(accessToken)) + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/beacon/BeaconFacetBuilder.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/beacon/BeaconFacetBuilder.java new file mode 100644 index 0000000..f863f09 --- /dev/null +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/beacon/BeaconFacetBuilder.java @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +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 build(String accessToken) { + var beaconAuthorization = beaconAuth.retrieveAuthorization(accessToken); + if (beaconAuthorization == null) { + return List.of(); + } + return service.listFilteringTermList(beaconAuthorization); + } +} diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/ckan/CkanFacetBuilder.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/ckan/CkanFacetBuilder.java new file mode 100644 index 0000000..901e2ae --- /dev/null +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/ckan/CkanFacetBuilder.java @@ -0,0 +1,87 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +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 build(String accessToken) { + var response = ckanQueryApi.packageSearch( + null, + null, + null, + 0, + 0, + selectedFacets, + accessToken + ); + + var nonNullSearchFacets = ofNullable(response.getResult()) + .map(PackagesSearchResult::getSearchFacets) + .orElseGet(Map::of); + + return facets(nonNullSearchFacets); + } + + private List facets(Map facets) { + return facets + .entrySet() + .stream() + .map(this::facet) + .toList(); + } + + private Facet facet(Map.Entry 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(); + } +} diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/quarkus/FacetsController.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/quarkus/FacetsController.java new file mode 100644 index 0000000..da1e420 --- /dev/null +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/infrastructure/quarkus/FacetsController.java @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +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(); + } +} diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/ports/IFacetBuilder.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/ports/IFacetBuilder.java new file mode 100644 index 0000000..358d49c --- /dev/null +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/facets/ports/IFacetBuilder.java @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +package io.github.genomicdatainfrastructure.discovery.facets.ports; + +import io.github.genomicdatainfrastructure.discovery.model.Facet; + +import java.util.List; + +public interface IFacetBuilder { + + List build(String accessToken); +} diff --git a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/BeaconFilteringTermsService.java b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/BeaconFilteringTermsService.java index 2dc52d7..eb7a337 100644 --- a/src/main/java/io/github/genomicdatainfrastructure/discovery/services/BeaconFilteringTermsService.java +++ b/src/main/java/io/github/genomicdatainfrastructure/discovery/services/BeaconFilteringTermsService.java @@ -61,6 +61,19 @@ public FacetGroup listFilteringTerms(String authorization) { .build(); } + @CacheResult(cacheName = "beacon-facets-cache") + public List 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 ) { @@ -116,6 +129,7 @@ private List 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()) diff --git a/src/main/openapi/discovery.yaml b/src/main/openapi/discovery.yaml index 2643d2c..db13d04 100644 --- a/src/main/openapi/discovery.yaml +++ b/src/main/openapi/discovery.yaml @@ -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: @@ -483,6 +501,9 @@ components: title: Facets Facet: properties: + facetGroup: + type: string + title: Facet group key: type: string title: Key diff --git a/src/test/java/io/github/genomicdatainfrastructure/discovery/api/RetrieveFacetsTest.java b/src/test/java/io/github/genomicdatainfrastructure/discovery/api/RetrieveFacetsTest.java new file mode 100644 index 0000000..ba6ba6e --- /dev/null +++ b/src/test/java/io/github/genomicdatainfrastructure/discovery/api/RetrieveFacetsTest.java @@ -0,0 +1,53 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +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.*; + +@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)) + .body("find { it.facetGroup == 'ckan' }.values", hasSize(greaterThan(0))) + .body("find { it.facetGroup == 'beacon' }.values", hasSize(greaterThan(0))) + .body("find { it.label == 'Human Phenotype Ontology' }.values", hasSize(greaterThan( + 0))); + } +} diff --git a/src/test/java/io/github/genomicdatainfrastructure/discovery/facets/RetrieveFacetsQueryTest.java b/src/test/java/io/github/genomicdatainfrastructure/discovery/facets/RetrieveFacetsQueryTest.java new file mode 100644 index 0000000..e280855 --- /dev/null +++ b/src/test/java/io/github/genomicdatainfrastructure/discovery/facets/RetrieveFacetsQueryTest.java @@ -0,0 +1,121 @@ +// SPDX-FileCopyrightText: 2024 PNED G.I.E. +// +// SPDX-License-Identifier: Apache-2.0 + +package io.github.genomicdatainfrastructure.discovery.facets; + +import io.github.genomicdatainfrastructure.discovery.facets.application.RetrieveFacetsQuery; +import io.github.genomicdatainfrastructure.discovery.facets.ports.IFacetBuilder; +import io.github.genomicdatainfrastructure.discovery.model.Facet; +import io.github.genomicdatainfrastructure.discovery.model.ValueLabel; +import jakarta.enterprise.inject.Instance; +import org.junit.Assert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.stream.Stream; + +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class RetrieveFacetsQueryTest { + + @Mock + private Instance facetBuilders; + + @Mock + private IFacetBuilder facetBuilderCkan; + + @Mock + private IFacetBuilder facetBuilderBeacon; + + @InjectMocks + private RetrieveFacetsQuery query; + + @BeforeEach + public void setUp() { + when(facetBuilders.stream()).thenReturn(Stream.of(facetBuilderCkan, facetBuilderBeacon)); + } + + @Test + public void shouldRetrieveAllFacets() { + var mockCkanFacets = List.of( + Facet.builder() + .key("tags") + .label("tags") + .facetGroup("ckan") + .values( + List.of(ValueLabel.builder() + .label("genomics") + .value("5") + .build())) + .build()); + + when(facetBuilderCkan.build(anyString())).thenReturn(mockCkanFacets); + + var mockBeaconFacets = List.of( + Facet.builder() + .key("Human Phenotype Ontology") + .label("ontology") + .facetGroup("beacon") + .values( + List.of(ValueLabel.builder() + .label("Motor delay") + .value("3") + .build())) + .build()); + when(facetBuilderBeacon.build(anyString())).thenReturn(mockBeaconFacets); + + var facets = query.execute("token"); + + Assert.assertNotNull(facets); + Assert.assertEquals(2, facets.size()); + + Assert.assertEquals("ckan", facets.get(0).getFacetGroup()); + Assert.assertEquals("tags", facets.get(0).getKey()); + Assert.assertEquals("tags", facets.get(0).getLabel()); + Assert.assertEquals("genomics", facets.get(0).getValues().get(0).getLabel()); + Assert.assertEquals("5", facets.get(0).getValues().get(0).getValue()); + + Assert.assertEquals("beacon", facets.get(1).getFacetGroup()); + Assert.assertEquals("Human Phenotype Ontology", facets.get(1).getKey()); + Assert.assertEquals("ontology", facets.get(1).getLabel()); + Assert.assertEquals("Motor delay", facets.get(1).getValues().get(0).getLabel()); + Assert.assertEquals("3", facets.get(1).getValues().get(0).getValue()); + } + + @Test + public void shouldRetrieveFacetsFromOneSourceWhenTheOtherIsNull() { + var mockCkanFacets = List.of( + Facet.builder() + .key("tags") + .label("tags") + .facetGroup("ckan") + .values( + List.of(ValueLabel.builder() + .label("genomics") + .value("5") + .build())) + .build()); + + when(facetBuilderCkan.build(anyString())).thenReturn(mockCkanFacets); + + when(facetBuilderBeacon.build(anyString())).thenReturn(null); + + var facets = query.execute("token"); + + Assert.assertNotNull(facets); + Assert.assertEquals(1, facets.size()); + + Assert.assertEquals("ckan", facets.get(0).getFacetGroup()); + Assert.assertEquals("tags", facets.get(0).getKey()); + Assert.assertEquals("tags", facets.get(0).getLabel()); + Assert.assertEquals("genomics", facets.get(0).getValues().get(0).getLabel()); + Assert.assertEquals("5", facets.get(0).getValues().get(0).getValue()); + } +} diff --git a/src/test/resources/mappings/package_search_facets.json b/src/test/resources/mappings/package_search_facets.json index bdc5eaf..82a244f 100644 --- a/src/test/resources/mappings/package_search_facets.json +++ b/src/test/resources/mappings/package_search_facets.json @@ -10,33 +10,325 @@ "Content-Type": "application/json" }, "jsonBody": { - "help": "https://ckan-test.healthdata.nl/api/3/action/help_show?name=package_search", + "help": "https://catalogue.portal.dev.gdi.lu/api/3/action/help_show?name=enhanced_package_search", "success": true, "result": { - "count": 3, + "count": 16, "facets": { - "organization": { - "lumc": 3 + "tags": { + "cancer": 5, + "colon": 5, + "genomics": 5, + "synthetic": 5, + "CINECA": 1, + "COVID-19": 1, + "VCF": 1, + "colorectal": 1, + "colorectal_tumor": 1, + "genomic": 1, + "long": 1, + "ngs": 1, + "normal_tumor_pair": 1, + "rectum": 1, + "tofu": 1, + "wgs": 1 }, - "theme": { - "https://publications.europa.eu/resource/authority/data-theme/HEAL": 3 + "organization": { + "umcg": 5, + "ega": 4, + "nbis": 3, + "csc-fi": 1, + "instituto-superior-tecnico": 1, + "lnds": 1, + "university-of-oslo": 1 }, - "conforms_to": { - "https://health-ri.sandbox.semlab-leiden.nl/profile/2f08228e-1789-40f8-84cd-28e3288c3604": 3 + "res_format": { + "vcf": 2, + "CSV": 1, + "JSON": 1, + "XLS": 1, + "ZIP": 1, + "fastq": 1, + "graphql": 1, + "jsonld": 1, + "ped": 1, + "rdf-jsonld": 1, + "rdf-n3": 1, + "rdf-nquads": 1, + "rdf-ntriples": 1, + "rdf-trig": 1, + "rdf-ttl": 1, + "rdf-xml": 1, + "ttl": 1 }, "access_rights": { - "https://health-ri.sandbox.semlab-leiden.nl/dataset/d73d04ba-23f7-429f-8506-3aa9dccb0435#accessRights": 3 + "http://publications.europa.eu/resource/authority/access-right/RESTRICTED": 5, + "https://staging-fdp.gdi.nbis.se/dataset/87495812-3201-4099-9478-1c60c9ef8c85#accessRights": 1 }, - "language": { - "https://publications.europa.eu/resource/authority/language/ENG": 3 - + "theme": { + "https://publications.europa.eu/resource/authority/data-theme/TECH": 5, + "http://publications.europa.eu/resource/authority/data-theme/HEAL": 2, + "https://en.wikipedia.org/wiki/Colorectal_cancer": 1, + "https://gdi.onemilliongenomes.eu": 1 + } + }, + "results": [], + "sort": "score desc, metadata_modified desc", + "search_facets": { + "tags": { + "title": "Keywords", + "items": [ + { + "name": "wgs", + "display_name": "wgs", + "count": 1 + }, + { + "name": "tofu", + "display_name": "tofu", + "count": 1 + }, + { + "name": "synthetic", + "display_name": "synthetic", + "count": 5 + }, + { + "name": "rectum", + "display_name": "rectum", + "count": 1 + }, + { + "name": "normal_tumor_pair", + "display_name": "normal_tumor_pair", + "count": 1 + }, + { + "name": "ngs", + "display_name": "ngs", + "count": 1 + }, + { + "name": "long", + "display_name": "long", + "count": 1 + }, + { + "name": "genomics", + "display_name": "genomics", + "count": 5 + }, + { + "name": "genomic", + "display_name": "genomic", + "count": 1 + }, + { + "name": "colorectal_tumor", + "display_name": "colorectal_tumor", + "count": 1 + }, + { + "name": "colorectal", + "display_name": "colorectal", + "count": 1 + }, + { + "name": "colon", + "display_name": "colon", + "count": 5 + }, + { + "name": "cancer", + "display_name": "cancer", + "count": 5 + }, + { + "name": "VCF", + "display_name": "VCF", + "count": 1 + }, + { + "name": "COVID-19", + "display_name": "COVID-19", + "count": 1 + }, + { + "name": "CINECA", + "display_name": "CINECA", + "count": 1 + } + ] }, - "publisher_name": { - "lumc": 3 + "organization": { + "title": "Publishers", + "items": [ + { + "name": "university-of-oslo", + "display_name": "university-of-oslo", + "count": 1 + }, + { + "name": "umcg", + "display_name": "umcg", + "count": 5 + }, + { + "name": "nbis", + "display_name": "nbis", + "count": 3 + }, + { + "name": "lnds", + "display_name": "lnds", + "count": 1 + }, + { + "name": "ega", + "display_name": "ega", + "count": 4 + }, + { + "name": "csc-fi", + "display_name": "csc-fi", + "count": 1 + }, + { + "name": "instituto-superior-tecnico", + "display_name": "instituto-superior-tecnico", + "count": 1 + } + ] }, "res_format": { + "title": "File Formats", + "items": [ + { + "name": "vcf", + "display_name": "vcf", + "count": 2 + }, + { + "name": "ttl", + "display_name": "ttl", + "count": 1 + }, + { + "name": "rdf-xml", + "display_name": "rdf-xml", + "count": 1 + }, + { + "name": "rdf-ttl", + "display_name": "rdf-ttl", + "count": 1 + }, + { + "name": "rdf-trig", + "display_name": "rdf-trig", + "count": 1 + }, + { + "name": "rdf-ntriples", + "display_name": "rdf-ntriples", + "count": 1 + }, + { + "name": "rdf-nquads", + "display_name": "rdf-nquads", + "count": 1 + }, + { + "name": "rdf-n3", + "display_name": "rdf-n3", + "count": 1 + }, + { + "name": "rdf-jsonld", + "display_name": "rdf-jsonld", + "count": 1 + }, + { + "name": "ped", + "display_name": "ped", + "count": 1 + }, + { + "name": "jsonld", + "display_name": "jsonld", + "count": 1 + }, + { + "name": "graphql", + "display_name": "graphql", + "count": 1 + }, + { + "name": "fastq", + "display_name": "fastq", + "count": 1 + }, + { + "name": "ZIP", + "display_name": "ZIP", + "count": 1 + }, + { + "name": "XLS", + "display_name": "XLS", + "count": 1 + }, + { + "name": "JSON", + "display_name": "JSON", + "count": 1 + }, + { + "name": "CSV", + "display_name": "CSV", + "count": 1 + } + ] }, - "provenance": { + "access_rights": { + "title": "Access Rights", + "items": [ + { + "name": "https://staging-fdp.gdi.nbis.se/dataset/87495812-3201-4099-9478-1c60c9ef8c85#accessRights", + "display_name": "https://staging-fdp.gdi.nbis.se/dataset/87495812-3201-4099-9478-1c60c9ef8c85#accessRights", + "count": 1 + }, + { + "name": "http://publications.europa.eu/resource/authority/access-right/RESTRICTED", + "display_name": "Restricted", + "count": 5 + } + ] + }, + "theme": { + "title": "Themes", + "items": [ + { + "name": "https://publications.europa.eu/resource/authority/data-theme/TECH", + "display_name": "Science and technology", + "count": 5 + }, + { + "name": "https://gdi.onemilliongenomes.eu", + "display_name": "GDI", + "count": 1 + }, + { + "name": "https://en.wikipedia.org/wiki/Colorectal_cancer", + "display_name": "Colorectal cancer", + "count": 1 + }, + { + "name": "http://publications.europa.eu/resource/authority/data-theme/HEAL", + "display_name": "Health", + "count": 2 + } + ] } } }