View Javadoc
1   package de.dlr.shepard.data.spatialdata.services;
2   
3   import de.dlr.shepard.common.exceptions.InvalidRequestException;
4   import de.dlr.shepard.data.spatialdata.io.SpatialDataPointIO;
5   import de.dlr.shepard.data.spatialdata.io.SpatialDataQueryParams;
6   import de.dlr.shepard.data.spatialdata.model.GeometryBuilder;
7   import de.dlr.shepard.data.spatialdata.model.SpatialDataPoint;
8   import de.dlr.shepard.data.spatialdata.model.geometryFilter.AxisAlignedBoundingBox;
9   import de.dlr.shepard.data.spatialdata.model.geometryFilter.BoundingSphere;
10  import de.dlr.shepard.data.spatialdata.model.geometryFilter.KNearestNeighbor;
11  import de.dlr.shepard.data.spatialdata.repositories.SpatialDataPointRepository;
12  import jakarta.enterprise.context.RequestScoped;
13  import jakarta.inject.Inject;
14  import jakarta.transaction.Transactional;
15  import java.util.List;
16  import java.util.stream.Collectors;
17  import org.locationtech.jts.geom.Coordinate;
18  
19  @RequestScoped
20  public class SpatialDataPointService {
21  
22    @Inject
23    SpatialDataPointRepository spatialDataPointRepository;
24  
25    @Inject
26    SpatialDataContainerService spatialDataContainerService;
27  
28    @Transactional
29    public void createSpatialDataPoints(Long containerId, List<SpatialDataPointIO> dataPoints) {
30      spatialDataContainerService.getContainer(containerId);
31      spatialDataContainerService.assertIsAllowedToEditContainer(containerId);
32  
33      final List<SpatialDataPoint> spatialGeometryList = mapSpatialDataPointIO(containerId, dataPoints);
34      spatialDataPointRepository.insert(containerId, spatialGeometryList.toArray(new SpatialDataPoint[0]));
35    }
36  
37    public List<SpatialDataPointIO> getSpatialDataPointIOs(
38      long containerId,
39      SpatialDataQueryParams spatialDataQueryParams
40    ) {
41      spatialDataContainerService.getContainer(containerId);
42  
43      List<String> validationErrors = spatialDataQueryParams.validate();
44      if (!validationErrors.isEmpty()) {
45        throw new InvalidRequestException("The following errors occurred: " + String.join(", ", validationErrors));
46      }
47      if (spatialDataQueryParams.getGeometryFilter() == null) return mapSpatialDataPoints(
48        spatialDataPointRepository.get(
49          containerId,
50          spatialDataQueryParams.getStartTime(),
51          spatialDataQueryParams.getEndTime(),
52          spatialDataQueryParams.getMetadata(),
53          spatialDataQueryParams.getMeasurementsFilters(),
54          spatialDataQueryParams.getLimit(),
55          spatialDataQueryParams.getSkip()
56        )
57      );
58      switch (spatialDataQueryParams.getGeometryFilter().getType()) {
59        case AXIS_ALIGNED_BOUNDING_BOX -> {
60          return getByAABoundingBox(
61            containerId,
62            (AxisAlignedBoundingBox) spatialDataQueryParams.getGeometryFilter(),
63            spatialDataQueryParams
64          );
65        }
66        case BOUNDING_SPHERE -> {
67          return getByBoundingSphere(
68            containerId,
69            (BoundingSphere) spatialDataQueryParams.getGeometryFilter(),
70            spatialDataQueryParams
71          );
72        }
73        case K_NEAREST_NEIGHBOR -> {
74          return getByKNN(
75            containerId,
76            (KNearestNeighbor) spatialDataQueryParams.getGeometryFilter(),
77            spatialDataQueryParams
78          );
79        }
80        case ORIENTED_BOUNDING_BOX -> throw new UnsupportedOperationException("not implemented");
81        default -> throw new Error("Unknown geometry filter type");
82      }
83    }
84  
85    @Transactional
86    public void deleteByContainerId(long containerId) {
87      spatialDataContainerService.getContainer(containerId);
88      spatialDataContainerService.assertIsAllowedToEditContainer(containerId);
89  
90      spatialDataPointRepository.deleteByContainerId(containerId);
91    }
92  
93    private List<SpatialDataPointIO> getByAABoundingBox(
94      long containerId,
95      AxisAlignedBoundingBox boundingBox,
96      SpatialDataQueryParams spatialDataQueryParams
97    ) {
98      spatialDataContainerService.getContainer(containerId);
99  
100     final Coordinate bottomLeft = new Coordinate(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ());
101     final Coordinate topRight = new Coordinate(boundingBox.getMaxX(), boundingBox.getMaxY(), boundingBox.getMaxZ());
102     return mapSpatialDataPoints(
103       spatialDataPointRepository.getByBoundingBox(
104         containerId,
105         bottomLeft,
106         topRight,
107         spatialDataQueryParams.getStartTime(),
108         spatialDataQueryParams.getEndTime(),
109         spatialDataQueryParams.getMetadata(),
110         spatialDataQueryParams.getMeasurementsFilters(),
111         spatialDataQueryParams.getLimit(),
112         spatialDataQueryParams.getSkip()
113       )
114     );
115   }
116 
117   private List<SpatialDataPointIO> getByBoundingSphere(
118     long containerId,
119     BoundingSphere boundingSphere,
120     SpatialDataQueryParams spatialDataQueryParams
121   ) {
122     spatialDataContainerService.getContainer(containerId);
123 
124     final Coordinate sphereCenter = new Coordinate(
125       boundingSphere.getCenterX(),
126       boundingSphere.getCenterY(),
127       boundingSphere.getCenterZ()
128     );
129 
130     return mapSpatialDataPoints(
131       spatialDataPointRepository.getByBoundingSphere(
132         containerId,
133         sphereCenter,
134         boundingSphere.getRadius(),
135         spatialDataQueryParams.getStartTime(),
136         spatialDataQueryParams.getEndTime(),
137         spatialDataQueryParams.getMetadata(),
138         spatialDataQueryParams.getMeasurementsFilters(),
139         spatialDataQueryParams.getLimit(),
140         spatialDataQueryParams.getSkip()
141       )
142     );
143   }
144 
145   private List<SpatialDataPointIO> getByKNN(
146     long containerId,
147     KNearestNeighbor knn,
148     SpatialDataQueryParams spatialDataQueryParams
149   ) {
150     spatialDataContainerService.getContainer(containerId);
151 
152     final Coordinate kCoordinate = new Coordinate(knn.getX(), knn.getY(), knn.getZ());
153     return mapSpatialDataPoints(
154       spatialDataPointRepository.getByKNN(
155         containerId,
156         kCoordinate,
157         knn.getK(),
158         spatialDataQueryParams.getStartTime(),
159         spatialDataQueryParams.getEndTime(),
160         spatialDataQueryParams.getMetadata(),
161         spatialDataQueryParams.getMeasurementsFilters()
162       )
163     );
164   }
165 
166   private List<SpatialDataPointIO> mapSpatialDataPoints(List<SpatialDataPoint> dataPoints) {
167     return dataPoints
168       .stream()
169       .map(point ->
170         new SpatialDataPointIO(
171           point.getTime(),
172           point.getPosition().getCoordinate().getX(),
173           point.getPosition().getCoordinate().getY(),
174           point.getPosition().getCoordinate().getZ(),
175           point.getMetadata(),
176           point.getMeasurements()
177         )
178       )
179       .collect(Collectors.toList());
180   }
181 
182   private List<SpatialDataPoint> mapSpatialDataPointIO(Long containerId, List<SpatialDataPointIO> dataPoints) {
183     return dataPoints
184       .stream()
185       .map(point ->
186         new SpatialDataPoint(
187           containerId,
188           point.getTimestamp(),
189           GeometryBuilder.fromXYZ(point.getX(), point.getY(), point.getZ()),
190           point.getMetadata(),
191           point.getMeasurements()
192         )
193       )
194       .collect(Collectors.toList());
195   }
196 }