Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: #3 add retrieve dataset endpoint #10

Merged
merged 1 commit into from
Apr 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions _http/ckan.http
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ GET https://ckan-test.healthdata.nl/api/3/action/package_search?fq=&sort=score+d

###
GET https://ckan-test.healthdata.nl/api/3/action/package_show?id=e1b3eff9-13eb-48b0-b180-7ecb76b84454

###
GET https://ckan-test.healthdata.nl/api/3/action/package_show?id=dummy
3 changes: 3 additions & 0 deletions _http/discovery.http
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ Content-Type: application/json
}]
}

###
GET http://localhost:8080/api/v1/datasets/e1b3eff9-13eb-48b0-b180-7ecb76b84454

###
GET http://localhost:8080/api/v1/datasets/dummy
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2024 PNED G.I.E.
//
// SPDX-License-Identifier: Apache-2.0

package io.github.genomicdatainfrastructure.discovery.api;

import static jakarta.ws.rs.core.Response.Status.NOT_FOUND;

import io.github.genomicdatainfrastructure.discovery.exceptions.DatasetNotFoundException;
import io.github.genomicdatainfrastructure.discovery.model.ErrorResponse;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

@Provider
public class DatasetNotFoundExceptionMapper implements
ExceptionMapper<DatasetNotFoundException> {

@Override
public Response toResponse(DatasetNotFoundException exception) {
var errorResponse = new ErrorResponse(
"Dataset Not Found",
NOT_FOUND.getStatusCode(),
exception.getMessage()
);

return Response
.status(NOT_FOUND)
.entity(errorResponse)
.type(MediaType.APPLICATION_JSON)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.github.genomicdatainfrastructure.discovery.model.DatasetsSearchResponse;
import io.github.genomicdatainfrastructure.discovery.model.RetrievedDataset;
import io.github.genomicdatainfrastructure.discovery.services.DatasetsSearchService;
import io.github.genomicdatainfrastructure.discovery.services.RetrieveDatasetService;
import io.quarkus.oidc.runtime.OidcJwtCallerPrincipal;
import io.quarkus.security.identity.SecurityIdentity;
import lombok.RequiredArgsConstructor;
Expand All @@ -17,16 +18,16 @@ public class DatasetQueryApiImpl implements DatasetQueryApi {

private final SecurityIdentity identity;
private final DatasetsSearchService datasetsSearchService;
private final RetrieveDatasetService retrievedDatasetService;

@Override
public DatasetsSearchResponse datasetSearch(DatasetSearchQuery datasetSearchQuery) {
return datasetsSearchService.search(accessToken(), datasetSearchQuery);
return datasetsSearchService.search(datasetSearchQuery, accessToken());
}

@Override
public RetrievedDataset retrieveDataset(String id) {
return RetrievedDataset.builder()
.build();
return retrievedDatasetService.retrieve(id, accessToken());
}

private String accessToken() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2024 PNED G.I.E.
//
// SPDX-License-Identifier: Apache-2.0

package io.github.genomicdatainfrastructure.discovery.exceptions;

public class DatasetNotFoundException extends RuntimeException {

private static final String MESSAGE = "Dataset %s not found";

public DatasetNotFoundException(String datasetId) {
super(MESSAGE.formatted(datasetId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public DatasetsSearchService(
this.ckanQueryApi = ckanQueryApi;
}

public DatasetsSearchResponse search(String accessToken, DatasetSearchQuery query) {
public DatasetsSearchResponse search(DatasetSearchQuery query, String accessToken) {
var response = ckanQueryApi.packageSearch(
query.getQuery(),
CkanFacetsQueryBuilder.buildFacetQuery(query.getFacets()),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// SPDX-FileCopyrightText: 2024 PNED G.I.E.
//
// SPDX-License-Identifier: Apache-2.0

package io.github.genomicdatainfrastructure.discovery.services;

import java.util.List;
import java.util.Objects;

import io.github.genomicdatainfrastructure.discovery.model.RetrievedDataset;
import io.github.genomicdatainfrastructure.discovery.model.RetrievedDistribution;
import io.github.genomicdatainfrastructure.discovery.model.ValueLabel;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.model.CkanOrganization;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.model.CkanPackage;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.model.CkanResource;

import static java.util.Optional.ofNullable;
import static java.util.function.Predicate.not;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class PackageShowMapper {

public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(
"yyyy-MM-dd'T'HH:mm:ss.SSSSSS"
);

private PackageShowMapper() {
brunopacheco1 marked this conversation as resolved.
Show resolved Hide resolved
// Utility class
}

public static RetrievedDataset from(CkanPackage ckanPackage) {
var catalogue = ofNullable(ckanPackage.getOrganization())
.map(CkanOrganization::getTitle)
.orElse(null);

return RetrievedDataset.builder()
.id(ckanPackage.getId())
.identifier(ckanPackage.getIdentifier())
.title(ckanPackage.getName())
.description(ckanPackage.getNotes())
.themes(values(ckanPackage.getTheme()))
.publisherName(ckanPackage.getPublisherName())
.catalogue(catalogue)
.createdAt(parse(ckanPackage.getMetadataCreated()))
.modifiedAt(parse(ckanPackage.getMetadataModified()))
.url(ckanPackage.getUrl())
.languages(values(ckanPackage.getLanguage()))
.contact(value(ckanPackage.getContactUri()))
.hasVersions(values(ckanPackage.getHasVersion()))
.accessRights(value(ckanPackage.getAccessRights()))
.conformsTo(values(ckanPackage.getConformsTo()))
.provenance(ckanPackage.getProvenance())
.spatial(value(ckanPackage.getSpatialUri()))
.distributions(distributions(ckanPackage))
.build();
}

private static List<ValueLabel> values(List<String> values) {
return ofNullable(values)
.orElseGet(List::of)
.stream()
.map(PackageShowMapper::value)
.filter(Objects::nonNull)
.toList();
}

private static ValueLabel value(String value) {
return ofNullable(value)
.filter(Objects::nonNull)
.filter(not(String::isBlank))
.map(it -> ValueLabel.builder()
.value(it)
.label(it)
.build())
.orElse(null);
}

private static LocalDateTime parse(String date) {
return ofNullable(date)
.map(it -> LocalDateTime.parse(it, DATE_FORMATTER))
.orElse(null);
}

private static List<RetrievedDistribution> distributions(CkanPackage ckanPackage) {
return ofNullable(ckanPackage.getResources())
.orElseGet(List::of)
.stream()
.map(PackageShowMapper::distribution)
.toList();
}

private static RetrievedDistribution distribution(CkanResource ckanResource) {
return RetrievedDistribution.builder()
.id(ckanResource.getId())
.title(ckanResource.getName())
.description(ckanResource.getDescription())
.format(value(ckanResource.getFormat()))
.uri(ckanResource.getUri())
.createdAt(parse(ckanResource.getCreated()))
.modifiedAt(parse(ckanResource.getLastModified()))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
import io.github.genomicdatainfrastructure.discovery.remote.ckan.model.PackagesSearchResult;
import java.util.List;
import java.util.Map;

import java.util.Objects;
import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;

import static java.util.Optional.ofNullable;
import static java.util.function.Predicate.not;

public class PackagesSearchResponseMapper {

Expand Down Expand Up @@ -120,10 +121,19 @@ private static List<ValueLabel> values(List<String> values) {
return ofNullable(values)
.orElseGet(List::of)
.stream()
.map(PackagesSearchResponseMapper::value)
.filter(Objects::nonNull)
.toList();
}

private static ValueLabel value(String value) {
return ofNullable(value)
.filter(Objects::nonNull)
.filter(not(String::isBlank))
.map(it -> ValueLabel.builder()
.value(it)
.label(it)
.build())
.toList();
.orElse(null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: 2024 PNED G.I.E.
//
// SPDX-License-Identifier: Apache-2.0

package io.github.genomicdatainfrastructure.discovery.services;

import org.eclipse.microprofile.rest.client.inject.RestClient;

import io.github.genomicdatainfrastructure.discovery.exceptions.DatasetNotFoundException;
import io.github.genomicdatainfrastructure.discovery.model.RetrievedDataset;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.api.CkanQueryApi;
import io.github.genomicdatainfrastructure.discovery.remote.ckan.model.CkanPackageShowResponse;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.ws.rs.WebApplicationException;

@ApplicationScoped
public class RetrieveDatasetService {

private final CkanQueryApi ckanQueryApi;

@Inject
public RetrieveDatasetService(
@RestClient CkanQueryApi ckanQueryApi
) {
this.ckanQueryApi = ckanQueryApi;
}

public RetrievedDataset retrieve(String id, String accessToken) {
var response = retrieveCkanPackage(id, accessToken);
return PackageShowMapper.from(response.getResult());
}

public CkanPackageShowResponse retrieveCkanPackage(String id, String accessToken) {
try {
return ckanQueryApi.packageShow(id, accessToken);
} catch (WebApplicationException e) {
if (e.getResponse().getStatus() == 404) {
throw new DatasetNotFoundException(id);
}
throw e;
}
}
}
31 changes: 30 additions & 1 deletion src/main/openapi/ckan.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,13 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CkanPackage"
$ref: "#/components/schemas/CkanPackageShowResponse"
"404":
description: The package not found
content:
application/json:
schema:
$ref: "#/components/schemas/CkanErrorResponse"
components:
schemas:
PackagesSearchResponse:
Expand Down Expand Up @@ -232,3 +238,26 @@ components:
- name
- description
- created
CkanPackageShowResponse:
type: object
properties:
help:
type: string
success:
type: boolean
result:
$ref: "#/components/schemas/CkanPackage"
CkanErrorResponse:
type: object
properties:
help:
type: string
success:
type: boolean
error:
type: object
properties:
__type:
type: string
message:
type: string
10 changes: 2 additions & 8 deletions src/main/openapi/discovery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,6 @@ paths:
application/json:
schema:
$ref: "#/components/schemas/RetrievedDataset"
"403":
description: Dataset is not visible to the user
content:
application/json:
schema:
$ref: "#/components/schemas/ErrorResponse"
"404":
description: Dataset not found
content:
Expand Down Expand Up @@ -229,7 +223,7 @@ components:
hasVersions:
type: array
items:
type: string
$ref: "#/components/schemas/ValueLabel"
title: Has Versions
accessRights:
$ref: "#/components/schemas/ValueLabel"
Expand Down Expand Up @@ -269,7 +263,7 @@ components:
type: string
title: Description
format:
type: string
$ref: "#/components/schemas/ValueLabel"
title: Format
uri:
type: string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-FileCopyrightText: 2024 PNED G.I.E.
//
// SPDX-License-Identifier: Apache-2.0

package io.github.genomicdatainfrastructure.discovery.api;

import io.quarkus.test.junit.QuarkusIntegrationTest;

@QuarkusIntegrationTest
public class RetrieveDatasetIT extends RetrieveDatasetTest {
}
Loading