Skip to content

Commit

Permalink
Merge branch 'feature/433814_total_elements' into 'develop'
Browse files Browse the repository at this point in the history
feature/433814_total_elements

See merge request upm-inesdata/inesdata-connector!21
  • Loading branch information
ralconada-gmv committed Jun 18, 2024
2 parents 940113a + f6db1fd commit e802dc1
Show file tree
Hide file tree
Showing 24 changed files with 609 additions and 0 deletions.
3 changes: 3 additions & 0 deletions extensions/count-elements-api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Count Elements API

Provides a management API for getting the total number of elements of an entity.
25 changes: 25 additions & 0 deletions extensions/count-elements-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
`java-library`
id("com.gmv.inesdata.edc-application")
}

dependencies {
api(project(":spi:count-elements-spi"))
api(libs.edc.spi.core)
implementation(libs.edc.spi.transform)
implementation(libs.edc.web.spi)

implementation(libs.edc.connector.core)
implementation(libs.edc.api.core)
implementation(libs.edc.lib.util)
implementation(libs.edc.lib.transform)
implementation(libs.edc.dsp.api.configuration)
implementation(libs.edc.api.management.config)
implementation(libs.swagger.annotations.jakarta)
implementation(libs.edc.transaction.spi)
implementation(libs.edc.lib.validator)
implementation(libs.edc.validator.spi)
implementation(libs.swagger.annotations.jakarta)
runtimeOnly(libs.edc.spi.jsonld)
runtimeOnly(libs.edc.json.ld.lib)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package org.upm.inesdata.countelements;

import jakarta.json.Json;
import org.eclipse.edc.connector.api.management.configuration.ManagementApiConfiguration;
import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provider;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.system.health.HealthCheckService;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.transaction.spi.TransactionContext;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.eclipse.edc.web.spi.WebService;
import org.upm.inesdata.countelements.controller.CountElementsApiController;
import org.upm.inesdata.countelements.service.CountElementsServiceImpl;
import org.upm.inesdata.countelements.transformer.JsonObjectFromCountElementTransformer;
import org.upm.inesdata.spi.countelements.index.CountElementsIndex;
import org.upm.inesdata.spi.countelements.service.CountElementsService;

import java.util.Map;

import static org.eclipse.edc.spi.constants.CoreConstants.JSON_LD;

/**
* Extension that provides an API for getting the total number of elements of an entity
*/
@Extension(value = CountElementsApiExtension.NAME)
public class CountElementsApiExtension implements ServiceExtension {

public static final String NAME = "CountElement Elements API Extension";

@Inject
private WebService webService;

@Inject
private TypeTransformerRegistry transformerRegistry;

@Inject(required = false)
private HealthCheckService healthCheckService;

@Inject
private ManagementApiConfiguration config;

@Inject
private TypeManager typeManager;

@Inject
private CountElementsIndex countElementsIndex;

@Inject
private TransactionContext transactionContext;

@Override
public String name() {
return NAME;
}

/**
* Provides a default countElementsService implementation
*/
@Provider(isDefault = true)
public CountElementsService countElementsService() {
return new CountElementsServiceImpl(countElementsIndex, transactionContext);
}

/**
* Initializes the service
*/
@Override
public void initialize(ServiceExtensionContext context) {
var factory = Json.createBuilderFactory(Map.of());
var jsonLdMapper = typeManager.getMapper(JSON_LD);
var managementApiTransformerRegistry = transformerRegistry.forContext("management-api");
managementApiTransformerRegistry.register(new JsonObjectFromCountElementTransformer(factory, jsonLdMapper));

var countElementsApiController = new CountElementsApiController(countElementsService(), managementApiTransformerRegistry);
webService.registerResource(config.getContextAlias(), countElementsApiController);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.upm.inesdata.countelements.controller;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.info.Info;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.eclipse.edc.api.model.ApiCoreSchema;

@OpenAPIDefinition(
info = @Info(description = "CountElement the elements of an entity.",
title = "CountElement Elements API", version = "1"))
@Tag(name = "CountElements")
public interface CountElementsApi {

/**
* Gets the total elements of an entity type.
*
* @param entityType entity type
* @return the total number of elements
*/
@Operation(description = "CountElement the elements of an entity",
responses = {
@ApiResponse(responseCode = "200", description = "The total number of elements",
content = @Content(schema = @Schema(implementation = Long.class))),
@ApiResponse(responseCode = "400", description = "Request was malformed, e.g. entityType was null",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class)))),
@ApiResponse(responseCode = "404", description = "The entity type given does not exist",
content = @Content(array = @ArraySchema(schema = @Schema(implementation = ApiCoreSchema.ApiErrorDetailSchema.class))))
}
)
long countElements(String entityType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.upm.inesdata.countelements.controller;

import jakarta.ws.rs.BadRequestException;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.edc.transform.spi.TypeTransformerRegistry;
import org.upm.inesdata.spi.countelements.service.CountElementsService;

import java.util.Objects;

@Produces({MediaType.APPLICATION_JSON})
@Path("/pagination")
public class CountElementsApiController implements CountElementsApi {

private final CountElementsService service;
private final TypeTransformerRegistry transformerRegistry;

public CountElementsApiController(CountElementsService service, TypeTransformerRegistry transformerRegistry) {
this.service = service;
this.transformerRegistry = transformerRegistry;
}

@GET
@Path("/count")
@Override
public long countElements(@QueryParam("type") String entityType) {
if (!Objects.equals(entityType, "asset") && !Objects.equals(entityType, "policyDefinition")
&& !Objects.equals(entityType, "contractDefinition")
&& !Objects.equals(entityType, "contractAgreement")
&& !Objects.equals(entityType, "transferProcess")) {
throw new BadRequestException("Entity type provided is not valid");
}

var count = service.countElements(entityType);

// JsonObject result = transformerRegistry.transform(count, JsonObject.class)
// .orElseThrow(f -> new EdcException(f.getFailureDetail()));

return count.getCount();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.upm.inesdata.countelements.service;

import org.eclipse.edc.transaction.spi.TransactionContext;
import org.upm.inesdata.spi.countelements.domain.CountElement;
import org.upm.inesdata.spi.countelements.index.CountElementsIndex;
import org.upm.inesdata.spi.countelements.service.CountElementsService;

public class CountElementsServiceImpl implements CountElementsService {
private final CountElementsIndex countElementsIndex;
private final TransactionContext transactionContext;

public CountElementsServiceImpl(CountElementsIndex countElementsIndex, TransactionContext transactionContext) {
this.countElementsIndex = countElementsIndex;
this.transactionContext = transactionContext;
}

@Override
public CountElement countElements(String entityType) {
return transactionContext.execute(() -> countElementsIndex.countElements(entityType));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.upm.inesdata.countelements.transformer;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.json.JsonBuilderFactory;
import jakarta.json.JsonObject;
import org.eclipse.edc.jsonld.spi.transformer.AbstractJsonLdTransformer;
import org.eclipse.edc.transform.spi.TransformerContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.upm.inesdata.spi.countelements.domain.CountElement;

import static org.upm.inesdata.spi.countelements.domain.CountElement.PROPERTY_COUNT;


/**
* Creates a JsonObject from a {@link CountElement}
*/
public class JsonObjectFromCountElementTransformer extends AbstractJsonLdTransformer<CountElement, JsonObject> {
private final ObjectMapper mapper;
private final JsonBuilderFactory jsonFactory;

/**
* Constructor
*/
public JsonObjectFromCountElementTransformer(JsonBuilderFactory jsonFactory, ObjectMapper jsonLdMapper) {
super(CountElement.class, JsonObject.class);
this.jsonFactory = jsonFactory;
this.mapper = jsonLdMapper;
}

@Override
public @Nullable JsonObject transform(@NotNull CountElement countElement, @NotNull TransformerContext context) {
var builder = jsonFactory.createObjectBuilder()
.add(PROPERTY_COUNT, countElement.getCount());

return builder.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.upm.inesdata.countelements.CountElementsApiExtension
17 changes: 17 additions & 0 deletions extensions/count-elements-sql/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
plugins {
`java-library`
id("com.gmv.inesdata.edc-application")
}

dependencies {
api(project(":spi:count-elements-spi"))
implementation(project(":extensions:count-elements-api"))
api(libs.edc.spi.core)
api(libs.edc.transaction.spi)
implementation(libs.edc.transaction.spi)
implementation(libs.edc.transaction.datasource.spi)
implementation(libs.edc.sql.core)
implementation(libs.edc.lib.util)
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.upm.inesdata.countelements.sql.index;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.edc.spi.persistence.EdcPersistenceException;
import org.eclipse.edc.sql.QueryExecutor;
import org.eclipse.edc.sql.store.AbstractSqlStore;
import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry;
import org.eclipse.edc.transaction.spi.TransactionContext;
import org.upm.inesdata.countelements.sql.index.schema.CountElementsStatements;
import org.upm.inesdata.spi.countelements.domain.CountElement;
import org.upm.inesdata.spi.countelements.index.CountElementsIndex;

import java.sql.SQLException;
import java.util.Objects;

/**
* Implementation of the CountElementsIndex with SQL databases
*/
public class SqlCountElementsIndex extends AbstractSqlStore implements CountElementsIndex {

private final CountElementsStatements countElementsStatements;

public SqlCountElementsIndex(DataSourceRegistry dataSourceRegistry,
String dataSourceName,
TransactionContext transactionContext,
ObjectMapper objectMapper,
CountElementsStatements countElementsStatements,
QueryExecutor queryExecutor) {
super(dataSourceRegistry, dataSourceName, transactionContext, objectMapper, queryExecutor);
this.countElementsStatements = Objects.requireNonNull(countElementsStatements);
}

@Override
public CountElement countElements(String entityType) {
try (var connection = getConnection()) {
var sql = countElementsStatements.getCount(entityType);
long count = queryExecutor.single(connection, true, r -> r.getLong(1), sql);
return CountElement.Builder.newInstance().count(count).build();
} catch (SQLException e) {
throw new EdcPersistenceException(e);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.upm.inesdata.countelements.sql.index;

import org.eclipse.edc.runtime.metamodel.annotation.Extension;
import org.eclipse.edc.runtime.metamodel.annotation.Inject;
import org.eclipse.edc.runtime.metamodel.annotation.Provides;
import org.eclipse.edc.runtime.metamodel.annotation.Setting;
import org.eclipse.edc.spi.system.ServiceExtension;
import org.eclipse.edc.spi.system.ServiceExtensionContext;
import org.eclipse.edc.spi.types.TypeManager;
import org.eclipse.edc.sql.QueryExecutor;
import org.eclipse.edc.transaction.datasource.spi.DataSourceRegistry;
import org.eclipse.edc.transaction.spi.TransactionContext;
import org.upm.inesdata.countelements.sql.index.schema.CountElementsStatements;
import org.upm.inesdata.countelements.sql.index.schema.postgres.PostgresDialectStatements;
import org.upm.inesdata.spi.countelements.index.CountElementsIndex;

/**
* Extension that counts elements in SQL databases
*/
@Provides({CountElementsIndex.class})
@Extension(value = "SQL count elements index")
public class SqlCountElementsIndexServiceExtension implements ServiceExtension {

/**
* Name of the vocabulary datasource.
*/
@Setting(required = true)
public static final String DATASOURCE_SETTING_NAME = "edc.datasource.countelements.name";

@Inject
private DataSourceRegistry dataSourceRegistry;

@Inject
private TransactionContext transactionContext;

@Inject(required = false)
private CountElementsStatements dialect;

@Inject
private TypeManager typeManager;

@Inject
private QueryExecutor queryExecutor;

@Override
public void initialize(ServiceExtensionContext context) {
var dataSourceName = context.getConfig().getString(DATASOURCE_SETTING_NAME, DataSourceRegistry.DEFAULT_DATASOURCE);

var sqlCountElementsLoader = new SqlCountElementsIndex(dataSourceRegistry, dataSourceName, transactionContext, typeManager.getMapper(),
getDialect(), queryExecutor);

context.registerService(CountElementsIndex.class, sqlCountElementsLoader);
}

private CountElementsStatements getDialect() {
return dialect != null ? dialect : new PostgresDialectStatements();
}
}
Loading

0 comments on commit e802dc1

Please sign in to comment.