Skip to content

Commit

Permalink
feat: implements versioning for FederatedCatalogApi (#208)
Browse files Browse the repository at this point in the history
  • Loading branch information
wolf4ood authored Jun 20, 2024
1 parent 597fbc5 commit bd774ec
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 259 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
import jakarta.json.JsonObject;
import org.eclipse.edc.api.model.ApiCoreSchema;

import javax.xml.catalog.Catalog;

@OpenAPIDefinition(
info = @Info(description = "This represents the Federated Catalog API. It serves the cached Catalogs fetched from the data providers.",
title = "Federated Catalog API", version = "v1"))
Expand All @@ -38,10 +36,82 @@ public interface FederatedCatalogApi {
requestBody = @RequestBody(content = @Content(schema = @Schema(implementation = ApiCoreSchema.QuerySpecSchema.class))),
responses = {
@ApiResponse(responseCode = "200", description = "A list of Catalog is returned, potentially empty",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = Catalog.class)))),
content = @Content(array = @ArraySchema(schema = @Schema(implementation = CatalogSchema.class)))),
@ApiResponse(responseCode = "500", description = "A Query could not be completed due to an internal error")
}

)
JsonArray getCachedCatalog(JsonObject querySpec);


@Schema(name = "Catalog", description = "DCAT catalog", example = CatalogSchema.CATALOG_EXAMPLE)
record CatalogSchema(
) {
public static final String CATALOG_EXAMPLE = """
{
"@id": "7df65569-8c59-4013-b1c0-fa14f6641bf2",
"@type": "dcat:Catalog",
"dcat:dataset": {
"@id": "bcca61be-e82e-4da6-bfec-9716a56cef35",
"@type": "dcat:Dataset",
"odrl:hasPolicy": {
"@id": "OGU0ZTMzMGMtODQ2ZS00ZWMxLThmOGQtNWQxNWM0NmI2NmY4:YmNjYTYxYmUtZTgyZS00ZGE2LWJmZWMtOTcxNmE1NmNlZjM1:NDY2ZTZhMmEtNjQ1Yy00ZGQ0LWFlZDktMjdjNGJkZTU4MDNj",
"@type": "odrl:Set",
"odrl:permission": {
"odrl:target": "bcca61be-e82e-4da6-bfec-9716a56cef35",
"odrl:action": {
"odrl:type": "http://www.w3.org/ns/odrl/2/use"
},
"odrl:constraint": {
"odrl:and": [
{
"odrl:leftOperand": "https://w3id.org/edc/v0.0.1/ns/inForceDate",
"odrl:operator": {
"@id": "odrl:gteq"
},
"odrl:rightOperand": "2023-07-07T07:19:58.585601395Z"
},
{
"odrl:leftOperand": "https://w3id.org/edc/v0.0.1/ns/inForceDate",
"odrl:operator": {
"@id": "odrl:lteq"
},
"odrl:rightOperand": "2023-07-12T07:19:58.585601395Z"
}
]
}
},
"odrl:prohibition": [],
"odrl:obligation": []
},
"dcat:distribution": [
{
"@type": "dcat:Distribution",
"dct:format": {
"@id": "HttpData"
},
"dcat:accessService": "5e839777-d93e-4785-8972-1005f51cf367"
}
],
"description": "description",
"id": "bcca61be-e82e-4da6-bfec-9716a56cef35"
},
"dcat:service": {
"@id": "5e839777-d93e-4785-8972-1005f51cf367",
"@type": "dcat:DataService",
"dct:terms": "connector",
"dct:endpointUrl": "http://localhost:16806/protocol"
},
"dspace:participantId": "urn:connector:provider",
"@context": {
"@vocab": "https://w3id.org/edc/v0.0.1/ns/",
"dct": "http://purl.org/dc/terms/",
"edc": "https://w3id.org/edc/v0.0.1/ns/",
"dcat": "http://www.w3.org/ns/dcat#",
"odrl": "http://www.w3.org/ns/odrl/2/",
"dspace": "https://w3id.org/dspace/v0.8/"
}
}
""";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
@Path("/federatedcatalog")
@Path("/v1alpha/catalog/query")
public class FederatedCatalogApiController implements FederatedCatalogApi {

private final QueryService queryService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@

package org.eclipse.edc.catalog.api.query;

import org.eclipse.edc.catalog.spi.FccApiContexts;
import org.eclipse.edc.catalog.spi.QueryService;
import org.eclipse.edc.jsonld.spi.JsonLd;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.spi.EdcException;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.system.apiversion.ApiVersionService;
import org.eclipse.edc.spi.system.apiversion.VersionRecord;
import org.eclipse.edc.spi.system.health.HealthCheckResult;
import org.eclipse.edc.spi.system.health.HealthCheckService;
import org.eclipse.edc.spi.types.TypeManager;
Expand All @@ -29,6 +31,9 @@
import org.eclipse.edc.web.jersey.providers.jsonld.ObjectMapperProvider;
import org.eclipse.edc.web.spi.WebService;

import java.io.IOException;

import static org.eclipse.edc.catalog.spi.FccApiContexts.CATALOG_QUERY;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_PREFIX;
import static org.eclipse.edc.policy.model.OdrlNamespace.ODRL_SCHEMA;
import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;
Expand All @@ -38,6 +43,9 @@ public class FederatedCatalogApiExtension implements ServiceExtension {

public static final String NAME = "Cache Query API Extension";
private static final String CATALOG_QUERY_SCOPE = "CATALOG_QUERY_API";

private static final String API_VERSION_JSON_FILE = "version.json";

@Inject
private WebService webService;

Expand All @@ -54,6 +62,9 @@ public class FederatedCatalogApiExtension implements ServiceExtension {
@Inject
private TypeTransformerRegistry transformerRegistry;

@Inject
private ApiVersionService apiVersionService;

@Override
public String name() {
return NAME;
Expand All @@ -64,15 +75,28 @@ public void initialize(ServiceExtensionContext context) {
jsonLd.registerNamespace(ODRL_PREFIX, ODRL_SCHEMA, CATALOG_QUERY_SCOPE);
var jsonLdMapper = typeManager.getMapper(JSON_LD);
var catalogController = new FederatedCatalogApiController(queryService, transformerRegistry);
webService.registerResource(FccApiContexts.CATALOG_QUERY, catalogController);
webService.registerResource(FccApiContexts.CATALOG_QUERY, new ObjectMapperProvider(jsonLdMapper));
webService.registerResource(FccApiContexts.CATALOG_QUERY, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, CATALOG_QUERY_SCOPE));
webService.registerResource(CATALOG_QUERY, catalogController);
webService.registerResource(CATALOG_QUERY, new ObjectMapperProvider(jsonLdMapper));
webService.registerResource(CATALOG_QUERY, new JerseyJsonLdInterceptor(jsonLd, jsonLdMapper, CATALOG_QUERY_SCOPE));

// contribute to the liveness probe
if (healthCheckService != null) {
var successResult = HealthCheckResult.Builder.newInstance().component("FCC Query API").build();
healthCheckService.addReadinessProvider(() -> successResult);
healthCheckService.addLivenessProvider(() -> successResult);
}
registerVersionInfo(getClass().getClassLoader());
}

private void registerVersionInfo(ClassLoader resourceClassLoader) {
try (var versionContent = resourceClassLoader.getResourceAsStream(API_VERSION_JSON_FILE)) {
if (versionContent == null) {
throw new EdcException("Version file not found or not readable.");
}
var content = typeManager.getMapper().readValue(versionContent, VersionRecord.class);
apiVersionService.addRecord(CATALOG_QUERY, content);
} catch (IOException e) {
throw new EdcException(e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"version": "1.0.0-alpha",
"urlPath": "/v1alpha",
"lastUpdated": "2024-06-19T11:00:00Z"
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@
@ApiTest
class FederatedCatalogApiControllerTest extends RestControllerTestBase {
private final InMemoryFederatedCatalogCache store = mock();
private static final String PATH = "/v1alpha/catalog/query";

@Test
void queryApi_whenEmptyResult() {
when(store.query(any())).thenReturn(Collections.emptyList());
baseRequest()
.contentType(JSON)
.body("{}")
.post("/federatedcatalog")
.post(PATH)
.then()
.log().ifError()
.statusCode(200)
Expand All @@ -72,7 +73,7 @@ void queryApi_whenResultsReturned() {
baseRequest()
.contentType(JSON)
.body("{}")
.post("/federatedcatalog")
.post(PATH)
.then()
.log().ifError()
.statusCode(200)
Expand All @@ -87,7 +88,7 @@ void queryApi_whenQueryUnsuccessful() {
baseRequest()
.contentType(JSON)
.body("{}")
.post("/federatedcatalog")
.post(PATH)
.then()
.statusCode(500);
}
Expand Down
Loading

0 comments on commit bd774ec

Please sign in to comment.