Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public interface DataProvider {
* The provider types.
*/
enum ProviderType {
TABLE, TREE_TIME_XY, TIME_GRAPH, DATA_TREE, NONE, GANTT_CHART, TREE_GENERIC_XY
TABLE, TREE_TIME_XY, TIME_GRAPH, DATA_TREE, GANTT_CHART, TREE_GENERIC_XY, DATA, NONE
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this breaks API

}

/**
Expand All @@ -47,6 +47,7 @@ enum ProviderType {
"Providers of type DATA_TREE only provide a tree with columns and don't have any XY nor time graph data associated with it. " +
"Providers of type GANTT_CHART use the same endpoint as TIME_GRAPH, but have a different x-axis (duration, page faults, etc.), with their own separate ranges. " +
"Providers of type TREE_GENERIC_XY supports XY view with non-time x-axis. " +
"Providers of type DATA provide an object with unspecified content. " +
"Providers of type NONE have no data to visualize. Can be used for grouping purposes and/or as data provider configurator.",
requiredMode = RequiredMode.REQUIRED)
ProviderType getType();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**********************************************************************
* Copyright (c) 2025 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

package org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model;

import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;

import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;

/**
* Contributes to the model used for TSP swagger-core annotations.
*/
@Schema(description = "A generic object with optional navigation parameters. " +
"If the next and/or previous navigation parameters are present, one of them can be returned as fetch parameter in a subsequent request to get the following or preceding object.")
public interface ObjectModel {

/**
* @return The object
*/
@NonNull
@Schema(requiredMode = RequiredMode.REQUIRED)
Object getObject();

/**
* @return The optional next navigation parameter object
*/
@Nullable
@Schema(requiredMode = RequiredMode.NOT_REQUIRED, description = "Navigation object to pass back in next request when browsing forward")
Object getNext();

/**
* @return The optional previous navigation parameter object
*/
@Nullable
@Schema(requiredMode = RequiredMode.NOT_REQUIRED, description = "Navigation object to pass back in next request when browsing backward")
Object getPrevious();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**********************************************************************
* Copyright (c) 2025 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

package org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model;

import org.eclipse.jdt.annotation.NonNull;

import com.fasterxml.jackson.annotation.JsonProperty;

import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;

/**
* Contributes to the model used for TSP swagger-core annotations.
*/
public interface ObjectQueryParameters {

/**
* @return The parameters.
*/
@NonNull
@Schema(requiredMode = RequiredMode.REQUIRED)
ObjectParameters getParameters();

/**
* Detailed object parameters
*/
interface ObjectParameters {
@JsonProperty("selection_range")
@ArraySchema(arraySchema = @Schema( requiredMode = RequiredMode.NOT_REQUIRED, description = "Selection range included when the output has the selectionRange capability" ), minItems = 2, maxItems = 2, schema = @Schema( type = "integer", format = "int64" ))
long[] getSelectionRange();

@JsonProperty("next")
@Schema(requiredMode = RequiredMode.NOT_REQUIRED, description = "Navigation object passed back from last response when browsing forward")
Object getNext();

@JsonProperty("previous")
@Schema(requiredMode = RequiredMode.NOT_REQUIRED, description = "Navigation object passed back from last response when browsing backward")
Object getPrevious();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/**********************************************************************
* Copyright (c) 2025 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

package org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model;

import org.eclipse.jdt.annotation.NonNull;

import io.swagger.v3.oas.annotations.media.Schema;

/**
* Contributes to the model used for TSP swagger-core annotations.
*/
@Schema(allOf = GenericResponse.class)
public interface ObjectResponse {

/**
* @return The model.
*/
@NonNull
ObjectModel getModel();
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,11 @@ public interface OutputCapabilities {
@Schema(description = "Optional, whether this output (data provider) can be deleted. 'false' if absent.")
@JsonProperty("canDelete")
boolean canDelete();

/**
* @return whether this output (data provider) uses the selection range. 'false' if absent.
*/
@Schema(description = "Optional, whether this output (data provider) uses the selection range. 'false' if absent.")
@JsonProperty("selectionRange")
boolean selectionRange();
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
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.OBJ;
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;
Expand Down Expand Up @@ -85,6 +86,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
Expand Down Expand Up @@ -116,6 +118,8 @@
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.GenericXYQueryParameters;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.LinesQueryParameters;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.MarkerSetsResponse;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.ObjectQueryParameters;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.ObjectResponse;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.OptionalQueryParameters;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.RequestedQueryParameters;
import org.eclipse.tracecompass.incubator.internal.trace.server.jersey.rest.core.model.StylesResponse;
Expand Down Expand Up @@ -161,6 +165,8 @@
import org.eclipse.tracecompass.tmf.core.model.annotations.AnnotationModel;
import org.eclipse.tracecompass.tmf.core.model.annotations.IOutputAnnotationProvider;
import org.eclipse.tracecompass.tmf.core.model.annotations.TraceAnnotationProvider;
import org.eclipse.tracecompass.tmf.core.model.object.IObjectDataProvider;
import org.eclipse.tracecompass.tmf.core.model.object.ObjectModel;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphArrow;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphDataProvider;
import org.eclipse.tracecompass.tmf.core.model.timegraph.ITimeGraphEntryModel;
Expand Down Expand Up @@ -288,6 +294,61 @@ public Response getProvider(
return ErrorResponseUtil.newErrorResponse(Status.NOT_FOUND, NO_SUCH_PROVIDER);
}

/**
* Query the provider for a result object.
*
* @param expUUID
* desired experiment UUID
* @param outputId
* Output ID for the data provider to query
* @param queryParameters
* Parameters to fetch a data tree as described by
* {@link QueryParameters}
* @return a {@link Response} with the result, if successful a
* {@link TmfModelResponse} with a {@link ObjectModel}
*/
@POST
@Path("/data/{outputId}/obj")
@Tag(name = OBJ)
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "API to get a result object", description = "Unique entry point to get a result object", responses = {
@ApiResponse(responseCode = "200", description = "Returns a result object.", content = @Content(schema = @Schema(implementation = ObjectResponse.class))),
@ApiResponse(responseCode = "400", description = INVALID_PARAMETERS, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "404", description = PROVIDER_NOT_FOUND, content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "405", description = NO_PROVIDER, content = @Content(schema = @Schema(implementation = ErrorResponse.class)))
})
public Response getObject(
@Parameter(description = EXP_UUID) @PathParam("expUUID") UUID expUUID,
@Parameter(description = OUTPUT_ID) @PathParam("outputId") String outputId,
@RequestBody(description = "Query parameters to fetch a result object", content = {
@Content(examples = @ExampleObject("{\"parameters\":{}}"), schema = @Schema(implementation = ObjectQueryParameters.class))
}, required = true) QueryParameters queryParameters) {
Response errorResponse = validateParameters(outputId, queryParameters);
if (errorResponse != null) {
return errorResponse;
}
Map<String, Object> params = queryParameters.getParameters();
try (FlowScopeLog scope = new FlowScopeLogBuilder(LOGGER, Level.FINE, "DataProviderService#getObject") //$NON-NLS-1$
.setCategory(outputId).build()) {
TmfExperiment experiment = ExperimentManagerService.getExperimentByUUID(expUUID);
if (experiment == null) {
return ErrorResponseUtil.newErrorResponse(Status.NOT_FOUND, NO_SUCH_TRACE);
}

IObjectDataProvider provider = manager.fetchOrCreateDataProvider(experiment,
outputId, IObjectDataProvider.class);

if (provider == null) {
// The analysis cannot be run on this trace
return ErrorResponseUtil.newErrorResponse(Status.METHOD_NOT_ALLOWED, NO_PROVIDER);
}

TmfModelResponse<ObjectModel> modelResponse = provider.fetchData(params, null);
return Response.ok(modelResponse).build();
}
}

/**
* Query the provider for the data tree entries.
*
Expand Down Expand Up @@ -1473,7 +1534,7 @@ private static Response validateParameters(String outputId, QueryParameters quer
if (outputId == null) {
return ErrorResponseUtil.newErrorResponse(Status.BAD_REQUEST, MISSING_OUTPUTID);
}
if (queryParameters == null) {
if (queryParameters == null || Objects.equals(queryParameters.getParameters(), null)) {
return ErrorResponseUtil.newErrorResponse(Status.BAD_REQUEST, MISSING_PARAMETERS);
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ public final class EndpointConstants {
static final String EXP = "Experiments"; //$NON-NLS-1$
static final String GXY = "Generic XY"; //$NON-NLS-1$
static final String IDF = "Identifier"; //$NON-NLS-1$
static final String OBJ = "Object"; //$NON-NLS-1$
static final String OCG = "Output Configurations"; //$NON-NLS-1$
static final String STY = "Styles"; //$NON-NLS-1$
static final String TGR = "TimeGraph"; //$NON-NLS-1$
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,15 @@ public void serialize(IDataProviderDescriptor value, JsonGenerator gen, Serializ
IDataProviderCapabilities cap = value.getCapabilities();
if (cap != DataProviderCapabilities.NULL_INSTANCE) {
gen.writeObjectFieldStart("capabilities"); //$NON-NLS-1$
gen.writeBooleanField("canCreate", cap.canCreate()); //$NON-NLS-1$
gen.writeBooleanField("canDelete", cap.canDelete()); //$NON-NLS-1$
if (cap.canCreate()) {
gen.writeBooleanField("canCreate", cap.canCreate()); //$NON-NLS-1$
}
if (cap.canDelete()) {
gen.writeBooleanField("canDelete", cap.canDelete()); //$NON-NLS-1$
}
if (cap.selectionRange()) {
gen.writeBooleanField("selectionRange", cap.selectionRange()); //$NON-NLS-1$
}
gen.writeEndObject();
}
gen.writeEndObject();
Expand Down
Loading