1 package de.dlr.shepard.context.semantic.endpoints; 2 3 import de.dlr.shepard.common.util.Constants; 4 import de.dlr.shepard.context.semantic.io.SemanticAnnotationIO; 5 import de.dlr.shepard.context.semantic.services.AnnotatableTimeseriesService; 6 import jakarta.enterprise.context.RequestScoped; 7 import jakarta.inject.Inject; 8 import jakarta.transaction.Transactional; 9 import jakarta.validation.Valid; 10 import jakarta.validation.constraints.NotNull; 11 import jakarta.validation.constraints.PositiveOrZero; 12 import jakarta.ws.rs.Consumes; 13 import jakarta.ws.rs.DELETE; 14 import jakarta.ws.rs.GET; 15 import jakarta.ws.rs.POST; 16 import jakarta.ws.rs.Path; 17 import jakarta.ws.rs.PathParam; 18 import jakarta.ws.rs.Produces; 19 import jakarta.ws.rs.core.MediaType; 20 import jakarta.ws.rs.core.Response; 21 import jakarta.ws.rs.core.Response.Status; 22 import java.util.stream.Collectors; 23 import org.eclipse.microprofile.openapi.annotations.Operation; 24 import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; 25 import org.eclipse.microprofile.openapi.annotations.media.Content; 26 import org.eclipse.microprofile.openapi.annotations.media.Schema; 27 import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; 28 import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody; 29 import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; 30 import org.eclipse.microprofile.openapi.annotations.tags.Tag; 31 32 @Consumes(MediaType.APPLICATION_JSON) 33 @Produces(MediaType.APPLICATION_JSON) 34 @Path( 35 Constants.TIMESERIES_CONTAINERS + 36 "/{" + 37 Constants.TIMESERIES_CONTAINER_ID + 38 "}/" + 39 Constants.TIMESERIES + 40 "/{" + 41 Constants.TIMESERIES_ID + 42 "}/" + 43 Constants.SEMANTIC_ANNOTATIONS 44 ) 45 @RequestScoped 46 public class AnnotatableTimeseriesRest { 47 48 @Inject 49 AnnotatableTimeseriesService annotatableTimeseriesService; 50 51 @GET 52 @Tag(name = Constants.TIMESERIES_CONTAINER) 53 @Operation( 54 operationId = "getAllAnnotationsOfTimeseries", 55 description = "Get all semantic annotations of a timeseries." 56 ) 57 @APIResponse( 58 description = "ok", 59 responseCode = "200", 60 content = @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = SemanticAnnotationIO.class)) 61 ) 62 @APIResponse(responseCode = "400", description = "bad request") 63 @APIResponse(responseCode = "401", description = "not authorized") 64 @APIResponse(responseCode = "403", description = "forbidden") 65 @APIResponse(responseCode = "404", description = "not found") 66 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID) 67 @Parameter(name = Constants.TIMESERIES_ID) 68 public Response getAllAnnotations( 69 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero Long containerId, 70 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId 71 ) { 72 var annotations = annotatableTimeseriesService.getAnnotations(containerId, timeseriesId); 73 return Response.ok(annotations.stream().map(SemanticAnnotationIO::new).collect(Collectors.toList())).build(); 74 } 75 76 @GET 77 @Path("/{" + Constants.SEMANTIC_ANNOTATION_ID + "}") 78 @Tag(name = Constants.TIMESERIES_CONTAINER) 79 @Operation( 80 operationId = "getSemanticAnnotationOfTimeseries", 81 description = "Get a specific semantic annotation of a timeseries." 82 ) 83 @APIResponse( 84 description = "ok", 85 responseCode = "200", 86 content = @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = SemanticAnnotationIO.class)) 87 ) 88 @APIResponse(responseCode = "400", description = "bad request") 89 @APIResponse(responseCode = "401", description = "not authorized") 90 @APIResponse(responseCode = "403", description = "forbidden") 91 @APIResponse(responseCode = "404", description = "not found") 92 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID) 93 @Parameter(name = Constants.TIMESERIES_ID) 94 @Parameter(name = Constants.SEMANTIC_ANNOTATION_ID) 95 public Response getAnnotationById( 96 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero Long containerId, 97 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId, 98 @PathParam(Constants.SEMANTIC_ANNOTATION_ID) @NotNull @PositiveOrZero Long annotationId 99 ) { 100 var annotation = annotatableTimeseriesService.getAnnotationById(containerId, timeseriesId, annotationId); 101 return Response.ok(new SemanticAnnotationIO(annotation)).build(); 102 } 103 104 @POST 105 @Tag(name = Constants.TIMESERIES_CONTAINER) 106 @Operation(operationId = "createAnnotationForTimeseries", description = "Create new annotation for a timeseries.") 107 @APIResponse( 108 description = "created", 109 responseCode = "201", 110 content = @Content(schema = @Schema(implementation = SemanticAnnotationIO.class)) 111 ) 112 @APIResponse(responseCode = "400", description = "bad request") 113 @APIResponse(responseCode = "401", description = "not authorized") 114 @APIResponse(responseCode = "403", description = "forbidden") 115 @APIResponse(responseCode = "404", description = "not found") 116 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID) 117 @Parameter(name = Constants.TIMESERIES_ID) 118 @Transactional 119 public Response createAnnotation( 120 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero Long containerId, 121 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId, 122 @RequestBody( 123 required = true, 124 content = @Content(schema = @Schema(implementation = SemanticAnnotationIO.class)) 125 ) @Valid SemanticAnnotationIO annotation 126 ) { 127 var result = annotatableTimeseriesService.createAnnotation(containerId, timeseriesId, annotation); 128 return Response.ok(new SemanticAnnotationIO(result)).status(Status.CREATED).build(); 129 } 130 131 @DELETE 132 @Path("/{" + Constants.SEMANTIC_ANNOTATION_ID + "}") 133 @Tag(name = Constants.TIMESERIES_CONTAINER) 134 @Operation(operationId = "deleteAnnotationOfTimeseries", description = "Delete annotation of timeseries.") 135 @APIResponse(description = "deleted", responseCode = "204") 136 @APIResponse(responseCode = "400", description = "bad request") 137 @APIResponse(responseCode = "401", description = "not authorized") 138 @APIResponse(responseCode = "403", description = "forbidden") 139 @APIResponse(responseCode = "404", description = "not found") 140 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID) 141 @Parameter(name = Constants.TIMESERIES_ID) 142 @Parameter(name = Constants.SEMANTIC_ANNOTATION_ID) 143 @Transactional 144 public Response deleteAnnotation( 145 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero Long containerId, 146 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId, 147 @PathParam(Constants.SEMANTIC_ANNOTATION_ID) @NotNull @PositiveOrZero Long annotationId 148 ) { 149 annotatableTimeseriesService.deleteAnnotation(containerId, timeseriesId, annotationId); 150 return Response.status(Status.NO_CONTENT).build(); 151 } 152 }