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.data.timeseries.services.TimeseriesContainerService; 6 import de.dlr.shepard.data.timeseries.services.TimeseriesService; 7 import jakarta.enterprise.context.RequestScoped; 8 import jakarta.inject.Inject; 9 import jakarta.transaction.Transactional; 10 import jakarta.validation.Valid; 11 import jakarta.validation.constraints.NotNull; 12 import jakarta.validation.constraints.PositiveOrZero; 13 import jakarta.ws.rs.Consumes; 14 import jakarta.ws.rs.DELETE; 15 import jakarta.ws.rs.GET; 16 import jakarta.ws.rs.NotFoundException; 17 import jakarta.ws.rs.POST; 18 import jakarta.ws.rs.Path; 19 import jakarta.ws.rs.PathParam; 20 import jakarta.ws.rs.Produces; 21 import jakarta.ws.rs.core.MediaType; 22 import jakarta.ws.rs.core.Response; 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 TimeseriesSemanticAnnotationRest extends SemanticAnnotationRest { 47 48 @Inject 49 TimeseriesService timeseriesService; 50 51 @Inject 52 TimeseriesContainerService timeseriesContainerService; 53 54 @GET 55 @Tag(name = Constants.TIMESERIES_CONTAINER) 56 @Operation( 57 operationId = "getAllAnnotationsOfTimeseries", 58 description = "Get all semantic annotations of a timeseries." 59 ) 60 @APIResponse( 61 description = "ok", 62 responseCode = "200", 63 content = @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = SemanticAnnotationIO.class)) 64 ) 65 @APIResponse(responseCode = "400", description = "bad request") 66 @APIResponse(responseCode = "401", description = "not authorized") 67 @APIResponse(responseCode = "403", description = "forbidden") 68 @APIResponse(responseCode = "404", description = "not found") 69 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID, deprecated = true) 70 @Parameter(name = Constants.TIMESERIES_ID) 71 public Response getAllAnnotations( 72 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero @Deprecated Long timeseriesContainerId, 73 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId 74 ) { 75 var timeseries = timeseriesService.getTimeseriesById(timeseriesId.longValue()); 76 return getAllByNeo4jId(timeseries.getId()); 77 } 78 79 @GET 80 @Path("/{" + Constants.SEMANTIC_ANNOTATION_ID + "}") 81 @Tag(name = Constants.TIMESERIES_CONTAINER) 82 @Operation( 83 operationId = "getSemanticAnnotationOfTimeseries", 84 description = "Get a specific semantic annotation of a timeseries." 85 ) 86 @APIResponse( 87 description = "ok", 88 responseCode = "200", 89 content = @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = SemanticAnnotationIO.class)) 90 ) 91 @APIResponse(responseCode = "400", description = "bad request") 92 @APIResponse(responseCode = "401", description = "not authorized") 93 @APIResponse(responseCode = "403", description = "forbidden") 94 @APIResponse(responseCode = "404", description = "not found") 95 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID, deprecated = true) 96 @Parameter(name = Constants.TIMESERIES_ID) 97 @Parameter(name = Constants.SEMANTIC_ANNOTATION_ID) 98 public Response getAnnotationById( 99 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero @Deprecated Long timeseriesContainerId, 100 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId, 101 @PathParam(Constants.SEMANTIC_ANNOTATION_ID) @NotNull @PositiveOrZero Long annotationId 102 ) { 103 var timeseries = timeseriesService.getTimeseriesById(timeseriesId.longValue()); 104 var annotation = timeseries 105 .getAnnotations() 106 .stream() 107 .filter(a -> a.getId().equals(annotationId)) 108 .findFirst() 109 .map(SemanticAnnotationIO::new) 110 .orElseThrow(NotFoundException::new); 111 return Response.ok(annotation).build(); 112 } 113 114 @POST 115 @Tag(name = Constants.TIMESERIES_CONTAINER) 116 @Operation(operationId = "createAnnotationForTimeseries", description = "Create new annotation for a timeseries.") 117 @APIResponse( 118 description = "created", 119 responseCode = "201", 120 content = @Content(schema = @Schema(implementation = SemanticAnnotationIO.class)) 121 ) 122 @APIResponse(responseCode = "400", description = "bad request") 123 @APIResponse(responseCode = "401", description = "not authorized") 124 @APIResponse(responseCode = "403", description = "forbidden") 125 @APIResponse(responseCode = "404", description = "not found") 126 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID, deprecated = true) 127 @Parameter(name = Constants.TIMESERIES_ID) 128 @Transactional 129 public Response createAnnotation( 130 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero @Deprecated Long timeseriesContainerId, 131 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId, 132 @RequestBody( 133 required = true, 134 content = @Content(schema = @Schema(implementation = SemanticAnnotationIO.class)) 135 ) @Valid SemanticAnnotationIO annotation 136 ) { 137 var timeseries = timeseriesService.getTimeseriesById(timeseriesId.longValue()); 138 return createByNeo4jId(timeseries.getId(), annotation); 139 } 140 141 @DELETE 142 @Path("/{" + Constants.SEMANTIC_ANNOTATION_ID + "}") 143 @Tag(name = Constants.TIMESERIES_CONTAINER) 144 @Operation(operationId = "deleteAnnotationOfTimeseries", description = "Delete annotation of timeseries.") 145 @APIResponse(description = "deleted", responseCode = "204") 146 @APIResponse(responseCode = "400", description = "bad request") 147 @APIResponse(responseCode = "401", description = "not authorized") 148 @APIResponse(responseCode = "403", description = "forbidden") 149 @APIResponse(responseCode = "404", description = "not found") 150 @Parameter(name = Constants.TIMESERIES_CONTAINER_ID, deprecated = true) 151 @Parameter(name = Constants.TIMESERIES_ID) 152 @Parameter(name = Constants.SEMANTIC_ANNOTATION_ID) 153 @Transactional 154 public Response deleteAnnotation( 155 @PathParam(Constants.TIMESERIES_CONTAINER_ID) @NotNull @PositiveOrZero @Deprecated Long timeseriesContainerId, 156 @PathParam(Constants.TIMESERIES_ID) @NotNull @PositiveOrZero Integer timeseriesId, 157 @PathParam(Constants.SEMANTIC_ANNOTATION_ID) @NotNull @PositiveOrZero Long annotationId 158 ) { 159 var timeseries = timeseriesService.getTimeseriesById(timeseriesId.longValue()); 160 timeseriesContainerService.assertIsAllowedToEditContainer(timeseries.getContainer().getId()); 161 var annotation = timeseries 162 .getAnnotations() 163 .stream() 164 .filter(a -> a.getId().equals(annotationId)) 165 .findFirst() 166 .orElseThrow(NotFoundException::new); 167 return delete(annotation.getId()); 168 } 169 }