View Javadoc
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 }