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.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 }