SpatialDataPointService.java
package de.dlr.shepard.data.spatialdata.services;
import de.dlr.shepard.common.exceptions.InvalidRequestException;
import de.dlr.shepard.data.spatialdata.io.SpatialDataPointIO;
import de.dlr.shepard.data.spatialdata.io.SpatialDataQueryParams;
import de.dlr.shepard.data.spatialdata.model.GeometryBuilder;
import de.dlr.shepard.data.spatialdata.model.SpatialDataPoint;
import de.dlr.shepard.data.spatialdata.model.geometryFilter.AxisAlignedBoundingBox;
import de.dlr.shepard.data.spatialdata.model.geometryFilter.BoundingSphere;
import de.dlr.shepard.data.spatialdata.model.geometryFilter.KNearestNeighbor;
import de.dlr.shepard.data.spatialdata.repositories.SpatialDataPointRepository;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.stream.Collectors;
import kotlin.NotImplementedError;
import org.locationtech.jts.geom.Coordinate;
@RequestScoped
public class SpatialDataPointService {
@Inject
SpatialDataPointRepository spatialDataPointRepository;
@Inject
SpatialDataContainerService spatialDataContainerService;
@Transactional
public void createSpatialDataPoints(Long containerId, List<SpatialDataPointIO> dataPoints) {
spatialDataContainerService.getContainer(containerId);
spatialDataContainerService.assertIsAllowedToEditContainer(containerId);
final List<SpatialDataPoint> spatialGeometryList = mapSpatialDataPointIO(containerId, dataPoints);
spatialDataPointRepository.insert(containerId, spatialGeometryList.toArray(new SpatialDataPoint[0]));
}
public List<SpatialDataPointIO> getSpatialDataPointIOs(
long containerId,
SpatialDataQueryParams spatialDataQueryParams
) {
spatialDataContainerService.getContainer(containerId);
List<String> validationErrors = spatialDataQueryParams.validate();
if (!validationErrors.isEmpty()) {
throw new InvalidRequestException("The following errors occurred: " + String.join(", ", validationErrors));
}
if (spatialDataQueryParams.getGeometryFilter() == null) return mapSpatialDataPoints(
spatialDataPointRepository.get(
containerId,
spatialDataQueryParams.getStartTime(),
spatialDataQueryParams.getEndTime(),
spatialDataQueryParams.getMetadata(),
spatialDataQueryParams.getMeasurementsFilters(),
spatialDataQueryParams.getLimit(),
spatialDataQueryParams.getSkip()
)
);
switch (spatialDataQueryParams.getGeometryFilter().getType()) {
case AXIS_ALIGNED_BOUNDING_BOX -> {
return getByAABoundingBox(
containerId,
(AxisAlignedBoundingBox) spatialDataQueryParams.getGeometryFilter(),
spatialDataQueryParams
);
}
case BOUNDING_SPHERE -> {
return getByBoundingSphere(
containerId,
(BoundingSphere) spatialDataQueryParams.getGeometryFilter(),
spatialDataQueryParams
);
}
case K_NEAREST_NEIGHBOR -> {
return getByKNN(
containerId,
(KNearestNeighbor) spatialDataQueryParams.getGeometryFilter(),
spatialDataQueryParams
);
}
case ORIENTED_BOUNDING_BOX -> throw new NotImplementedError("not implemented");
default -> throw new Error("Unknown geometry filter type");
}
}
@Transactional
public void deleteByContainerId(long containerId) {
spatialDataContainerService.getContainer(containerId);
spatialDataContainerService.assertIsAllowedToEditContainer(containerId);
spatialDataPointRepository.deleteByContainerId(containerId);
}
private List<SpatialDataPointIO> getByAABoundingBox(
long containerId,
AxisAlignedBoundingBox boundingBox,
SpatialDataQueryParams spatialDataQueryParams
) {
spatialDataContainerService.getContainer(containerId);
final Coordinate bottomLeft = new Coordinate(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ());
final Coordinate topRight = new Coordinate(boundingBox.getMaxX(), boundingBox.getMaxY(), boundingBox.getMaxZ());
return mapSpatialDataPoints(
spatialDataPointRepository.getByBoundingBox(
containerId,
bottomLeft,
topRight,
spatialDataQueryParams.getStartTime(),
spatialDataQueryParams.getEndTime(),
spatialDataQueryParams.getMetadata(),
spatialDataQueryParams.getMeasurementsFilters(),
spatialDataQueryParams.getLimit(),
spatialDataQueryParams.getSkip()
)
);
}
private List<SpatialDataPointIO> getByBoundingSphere(
long containerId,
BoundingSphere boundingSphere,
SpatialDataQueryParams spatialDataQueryParams
) {
spatialDataContainerService.getContainer(containerId);
final Coordinate sphereCenter = new Coordinate(
boundingSphere.getCenterX(),
boundingSphere.getCenterY(),
boundingSphere.getCenterZ()
);
return mapSpatialDataPoints(
spatialDataPointRepository.getByBoundingSphere(
containerId,
sphereCenter,
boundingSphere.getRadius(),
spatialDataQueryParams.getStartTime(),
spatialDataQueryParams.getEndTime(),
spatialDataQueryParams.getMetadata(),
spatialDataQueryParams.getMeasurementsFilters(),
spatialDataQueryParams.getLimit(),
spatialDataQueryParams.getSkip()
)
);
}
private List<SpatialDataPointIO> getByKNN(
long containerId,
KNearestNeighbor knn,
SpatialDataQueryParams spatialDataQueryParams
) {
spatialDataContainerService.getContainer(containerId);
final Coordinate kCoordinate = new Coordinate(knn.getX(), knn.getY(), knn.getZ());
return mapSpatialDataPoints(
spatialDataPointRepository.getByKNN(
containerId,
kCoordinate,
knn.getK(),
spatialDataQueryParams.getStartTime(),
spatialDataQueryParams.getEndTime(),
spatialDataQueryParams.getMetadata(),
spatialDataQueryParams.getMeasurementsFilters()
)
);
}
private List<SpatialDataPointIO> mapSpatialDataPoints(List<SpatialDataPoint> dataPoints) {
return dataPoints
.stream()
.map(point ->
new SpatialDataPointIO(
point.getTime(),
point.getPosition().getCoordinate().getX(),
point.getPosition().getCoordinate().getY(),
point.getPosition().getCoordinate().getZ(),
point.getMetadata(),
point.getMeasurements()
)
)
.collect(Collectors.toList());
}
private List<SpatialDataPoint> mapSpatialDataPointIO(Long containerId, List<SpatialDataPointIO> dataPoints) {
return dataPoints
.stream()
.map(point ->
new SpatialDataPoint(
containerId,
point.getTimestamp(),
GeometryBuilder.fromXYZ(point.getX(), point.getY(), point.getZ()),
point.getMetadata(),
point.getMeasurements()
)
)
.collect(Collectors.toList());
}
}