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 }