Skip to content

Commit

Permalink
server: Implement support for customizable data providers
Browse files Browse the repository at this point in the history
Update skeleton endpoints in DataProviderService for that.
Use ITmfDataProviderConfigurator interface for that.

Signed-off-by: Bernd Hufmann <[email protected]>
  • Loading branch information
bhufmann committed Oct 22, 2024
1 parent 16c5413 commit fcbdca6
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.MISSING_OUTPUTID;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.MISSING_PARAMETERS;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.NO_PROVIDER;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.NO_SUCH_CONFIGURATION;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.NO_SUCH_CONFIGURATION_TYPE;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.NO_SUCH_DERIVED_PROVIDER;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.NO_SUCH_PROVIDER;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.NO_SUCH_TRACE;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.OCG;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.ONE_OF;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.OUTPUT_ID;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.PROVIDER_NOT_FOUND;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.PROVIDER_CONFIG_NOT_FOUND;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.STY;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.TABLE_TIMES;
import static org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.services.EndpointConstants.TGR;
Expand Down Expand Up @@ -139,10 +142,16 @@
import org.eclipse.tracecompass.tmf.analysis.xml.core.module.TmfXmlUtils;
import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModuleHelper;
import org.eclipse.tracecompass.tmf.core.analysis.TmfAnalysisManager;
import org.eclipse.tracecompass.tmf.core.config.ITmfConfiguration;
import org.eclipse.tracecompass.tmf.core.config.ITmfConfigurationSourceType;
import org.eclipse.tracecompass.tmf.core.config.ITmfDataProviderConfigurator;
import org.eclipse.tracecompass.tmf.core.config.TmfConfiguration;
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderManager;
import org.eclipse.tracecompass.tmf.core.dataprovider.DataProviderParameterUtils;
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor;
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderDescriptor.ProviderType;
import org.eclipse.tracecompass.tmf.core.dataprovider.IDataProviderFactory;
import org.eclipse.tracecompass.tmf.core.exceptions.TmfConfigurationException;
import org.eclipse.tracecompass.tmf.core.model.CommonStatusMessage;
import org.eclipse.tracecompass.tmf.core.model.DataProviderDescriptor;
import org.eclipse.tracecompass.tmf.core.model.IOutputStyleProvider;
Expand Down Expand Up @@ -252,16 +261,11 @@ public Response getProvider(
if (experiment == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_TRACE).build();
}
List<IDataProviderDescriptor> list = DataProviderManager.getInstance().getAvailableProviders(experiment);
list.addAll(getXmlDataProviderDescriptors(experiment, EnumSet.of(OutputType.TIME_GRAPH)));
list.addAll(getXmlDataProviderDescriptors(experiment, EnumSet.of(OutputType.XY)));

Optional<IDataProviderDescriptor> provider = list.stream().filter(p -> p.getId().equals(outputId)).findFirst();

if (provider.isPresent()) {
return Response.ok(provider.get()).build();
IDataProviderDescriptor provider = getDescriptor(experiment, outputId);
if (provider != null) {
return Response.ok(provider).build();
}

return Response.status(Status.NOT_FOUND).build();
}

Expand Down Expand Up @@ -1152,23 +1156,33 @@ public Response getStyles(
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Get the list of configuration types defined on the server for a given output and experiment", responses = {
@ApiResponse(responseCode = "200", description = "Returns a list of configuration types that this output supports.", content = @Content(array = @ArraySchema(schema = @Schema(implementation = org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.ConfigurationSourceType.class)))),
@ApiResponse(responseCode = "404", description = PROVIDER_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_CONFIG_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
})
public Response getConfigurationTypes(
@Parameter(description = EXP_UUID) @PathParam("expUUID") UUID expUUID,
@Parameter(description = OUTPUT_ID) @PathParam("outputId") String outputId
) {
return Response.status(Status.NOT_IMPLEMENTED).entity("Get all configuration types for a given output").build(); //$NON-NLS-1$
}

private static Response validateParameters(String outputId, QueryParameters queryParameters) {
TmfExperiment experiment = ExperimentManagerService.getExperimentByUUID(expUUID);
if (experiment == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_TRACE).build();
}

if (outputId == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_OUTPUTID).build();
}
if (queryParameters == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_PARAMETERS).build();

IDataProviderDescriptor sourceDescriptor = getDescriptor(experiment, outputId);
IDataProviderFactory factory = manager.getFactory(outputId);
if (sourceDescriptor == null || factory == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER).build();
}
return null;

ITmfDataProviderConfigurator configurator = factory.getAdapter(ITmfDataProviderConfigurator.class);
if (configurator != null) {
return Response.ok(configurator.getConfigurationSourceTypes()).build();
}
return Response.ok(Collections.emptyList()).build();
}

/**
Expand All @@ -1188,14 +1202,40 @@ private static Response validateParameters(String outputId, QueryParameters quer
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Get a single configuration source type defined on the server for a given data provider and experiment.", responses = {
@ApiResponse(responseCode = "200", description = "Returns a single configuration source type", content = @Content(schema = @Schema(implementation = org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.ConfigurationSourceType.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = NO_SUCH_CONFIGURATION, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "400", description = INVALID_PARAMETERS, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_CONFIG_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
})
public Response getConfigurationType(
@Parameter(description = EXP_UUID) @PathParam("expUUID") UUID expUUID,
@Parameter(description = OUTPUT_ID) @PathParam("outputId") String outputId,
@Parameter(description = CFG_TYPE_ID) @PathParam("typeId") String typeId) {
return Response.status(Status.NOT_IMPLEMENTED).entity("Get a configuration type for a given output and typeId").build(); //$NON-NLS-1$

TmfExperiment experiment = ExperimentManagerService.getExperimentByUUID(expUUID);
if (experiment == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_TRACE).build();
}

if (outputId == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_OUTPUTID).build();
}

IDataProviderDescriptor sourceDescriptor = getDescriptor(experiment, outputId);
IDataProviderFactory factory = manager.getFactory(outputId);
if (sourceDescriptor == null || factory == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER).build();
}

ITmfDataProviderConfigurator configurator = factory.getAdapter(ITmfDataProviderConfigurator.class);
if (configurator == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER).build();
}

Optional<ITmfConfigurationSourceType> optional = configurator.getConfigurationSourceTypes().stream().filter(type -> type.getId().equals(typeId)).findAny();

if (!optional.isPresent()) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_CONFIGURATION_TYPE).build(); //$NON-NLS-1$
}
return Response.ok(optional.get()).build();
}

/**
Expand All @@ -1210,6 +1250,7 @@ public Response getConfigurationType(
* the query parameters used to create a data provider
* @return a list of data provider descriptors
*/
@SuppressWarnings("null")
@POST
@Path("/{outputId}")
@Tag(name = OCG)
Expand All @@ -1218,16 +1259,53 @@ public Response getConfigurationType(
@Operation(summary = "Get the list of outputs for this configuration", responses = {
@ApiResponse(responseCode = "200", description = "Returns a list of output provider descriptors", content = @Content(array = @ArraySchema(schema = @Schema(implementation = DataProvider.class)))),
@ApiResponse(responseCode = "400", description = INVALID_PARAMETERS, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = NO_SUCH_CONFIGURATION, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_CONFIG_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
})
public Response createDataProvider(
@Parameter(description = EXP_UUID) @PathParam("expUUID") UUID expUUID,
@Parameter(description = OUTPUT_ID) @PathParam("outputId") String outputId,
@RequestBody(description = CFG_CREATE_DESC + " " + CFG_KEYS_DESC, content = {
@Content(schema = @Schema(implementation = org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.ConfigurationQueryParameters.class))
}, required = true) ConfigurationQueryParameters queryParameters) {
return Response.status(Status.NOT_IMPLEMENTED).entity("POST a configuration to a given output to create derived output").build(); //$NON-NLS-1$

try (FlowScopeLog scope = new FlowScopeLogBuilder(LOGGER, Level.FINE, "DataProviderService#createDataProvider") //$NON-NLS-1$
.setCategory(outputId).build()) {
TmfExperiment experiment = ExperimentManagerService.getExperimentByUUID(expUUID);
if (experiment == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_TRACE).build();
}

Response errorResponse = validateOutputConfigParameters(outputId, queryParameters);
if (errorResponse != null) {
return errorResponse;
}

IDataProviderFactory factory = manager.getFactory(outputId);
if (factory == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER).build();
}

ITmfDataProviderConfigurator configurator = factory.getAdapter(ITmfDataProviderConfigurator.class);
if (configurator == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER).build();
}

ITmfConfiguration inputConfig = new TmfConfiguration.Builder()
.setName(queryParameters.getName())
.setDescription(queryParameters.getDescription())
.setSourceTypeId(queryParameters.getTypeId())
.setParameters(queryParameters.getParameters())
.build();
String typeId = inputConfig.getSourceTypeId();
Optional<ITmfConfigurationSourceType> optional = configurator.getConfigurationSourceTypes().stream().filter(type -> type.getId().equals(typeId)).findAny();
if (!optional.isPresent()) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_CONFIGURATION_TYPE).build();
}
IDataProviderDescriptor returnDescr = configurator.createDataProviderDescriptors(experiment, inputConfig);
return Response.ok(returnDescr).build();
} catch (TmfConfigurationException e) {
return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
}
}

/**
Expand All @@ -1245,17 +1323,88 @@ public Response createDataProvider(
@Path("/{outputId}/{derivedOutputId}")
@Tag(name = OCG)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Delete a configuration instance of a given configuration source type", responses = {
@Operation(summary = "Delete a configuration instance of a given configuration type", responses = {
@ApiResponse(responseCode = "200", description = "The derived data provider (and it's configuration) was successfully deleted", content = @Content(schema = @Schema(implementation = org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.Configuration.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = NO_SUCH_CONFIGURATION, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "500", description = "Internal trace-server error while trying to delete output", content = @Content(schema = @Schema(implementation = String.class)))
@ApiResponse(responseCode = "400", description = INVALID_PARAMETERS, content = @Content(schema = @Schema(implementation = String.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_CONFIG_NOT_FOUND, content = @Content(schema = @Schema(implementation = String.class))),
})
public Response deleteDerivedOutput(
@Parameter(description = EXP_UUID) @PathParam("expUUID") UUID expUUID,
@Parameter(description = OUTPUT_ID) @PathParam("outputId") String outputId,
@Parameter(description = OUTPUT_ID) @PathParam("derivedOutputId") String derivedOutputId) {
return Response.status(Status.NOT_IMPLEMENTED).entity("DELETE derived output").build(); //$NON-NLS-1$

if (outputId == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_OUTPUTID + " (parent)").build(); //$NON-NLS-1$
}

if (derivedOutputId == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_OUTPUTID + " (derived)").build(); //$NON-NLS-1$
}

try (FlowScopeLog scope = new FlowScopeLogBuilder(LOGGER, Level.FINE, "DataProviderService#removeDataProvider") //$NON-NLS-1$
.setCategory(outputId).build()) {
TmfExperiment experiment = ExperimentManagerService.getExperimentByUUID(expUUID);
if (experiment == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_TRACE).build();
}

IDataProviderDescriptor parentDescriptor = getDescriptor(experiment, outputId);
if (parentDescriptor == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER + ": " + outputId).build(); //$NON-NLS-1$
}

IDataProviderDescriptor derivedDescriptor = getDescriptor(experiment, derivedOutputId);
if (derivedDescriptor == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_DERIVED_PROVIDER + ": " + derivedOutputId).build(); //$NON-NLS-1$
}

IDataProviderFactory factory = manager.getFactory(outputId);
if (factory == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER).build();
}

ITmfDataProviderConfigurator configurator = factory.getAdapter(ITmfDataProviderConfigurator.class);
if (configurator == null) {
return Response.status(Status.NOT_FOUND).entity(NO_SUCH_PROVIDER).build();
}
configurator.removeDataProviderDescriptor(experiment, derivedDescriptor);
return Response.ok().build();
} catch (TmfConfigurationException e) {
return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
}
}

private static Response validateParameters(String outputId, QueryParameters queryParameters) {
if (outputId == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_OUTPUTID).build();
}
if (queryParameters == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_PARAMETERS).build();
}
return null;
}

private static Response validateOutputConfigParameters(String outputId, ConfigurationQueryParameters queryParameters) {
if (outputId == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_OUTPUTID).build();
}
if (queryParameters == null) {
return Response.status(Status.BAD_REQUEST).entity(MISSING_PARAMETERS).build();
}

return null;
}

private @Nullable IDataProviderDescriptor getDescriptor(@NonNull ITmfTrace experiment, @NonNull String outputId) {
List<IDataProviderDescriptor> list = manager.getAvailableProviders(experiment);
list.addAll(getXmlDataProviderDescriptors(experiment, EnumSet.of(OutputType.TIME_GRAPH)));
list.addAll(getXmlDataProviderDescriptors(experiment, EnumSet.of(OutputType.XY)));

Optional<IDataProviderDescriptor> provider = list.stream().filter(p -> p.getId().equals(outputId)).findFirst();
if (provider.isPresent()) {
return provider.get();
}
return null;
}

}
Loading

0 comments on commit fcbdca6

Please sign in to comment.