From 0655289d58a30f92c98c9345e88d43a31f8d34b7 Mon Sep 17 00:00:00 2001 From: flonix8 Date: Wed, 18 Feb 2026 18:52:42 +0100 Subject: [PATCH 1/6] Add notion of compass direction --- .../analytics/entity/MetadataEntity.java | 11 +++++++++++ .../observatory/entity/ObservationJobEntity.java | 13 ++++++++++++- .../db/migration/analytics/V3_0__add_direction.sql | 2 ++ .../migration/observatory/V4_0__add_direction.sql | 2 ++ .../starwit/service/analytics/MetadataService.java | 1 + .../service/observatory/ObservationJobService.java | 1 + 6 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 persistence/src/main/resources/db/migration/analytics/V3_0__add_direction.sql create mode 100644 persistence/src/main/resources/db/migration/observatory/V4_0__add_direction.sql diff --git a/persistence/src/main/java/de/starwit/persistence/analytics/entity/MetadataEntity.java b/persistence/src/main/java/de/starwit/persistence/analytics/entity/MetadataEntity.java index fe696ba..1175d21 100644 --- a/persistence/src/main/java/de/starwit/persistence/analytics/entity/MetadataEntity.java +++ b/persistence/src/main/java/de/starwit/persistence/analytics/entity/MetadataEntity.java @@ -35,6 +35,9 @@ public class MetadataEntity extends AbstractEntity { @Column(name = "observation_area_id") private Long observationAreaId; + @Column(name = "direction") + private String direction; + @OneToMany(mappedBy = "metadata", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private List geometryCoordinates; @@ -93,5 +96,13 @@ public Long getObservationAreaId() { public void setObservationAreaId(Long observationAreaId) { this.observationAreaId = observationAreaId; } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } } \ No newline at end of file diff --git a/persistence/src/main/java/de/starwit/persistence/observatory/entity/ObservationJobEntity.java b/persistence/src/main/java/de/starwit/persistence/observatory/entity/ObservationJobEntity.java index 3e7b27f..665e749 100644 --- a/persistence/src/main/java/de/starwit/persistence/observatory/entity/ObservationJobEntity.java +++ b/persistence/src/main/java/de/starwit/persistence/observatory/entity/ObservationJobEntity.java @@ -56,7 +56,10 @@ public class ObservationJobEntity extends AbstractEntity { @Column(name = "center_latitude") private BigDecimal centerLatitude; - + + @Column(name = "direction") + private String direction; + @NotNull @OneToMany(mappedBy = "observationJob", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private List geometryPoints; @@ -148,5 +151,13 @@ public BigDecimal getCenterLatitude() { public void setCenterLatitude(BigDecimal centerLatitude) { this.centerLatitude = centerLatitude; } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } } diff --git a/persistence/src/main/resources/db/migration/analytics/V3_0__add_direction.sql b/persistence/src/main/resources/db/migration/analytics/V3_0__add_direction.sql new file mode 100644 index 0000000..b7a2d14 --- /dev/null +++ b/persistence/src/main/resources/db/migration/analytics/V3_0__add_direction.sql @@ -0,0 +1,2 @@ +ALTER TABLE "metadata" + ADD COLUMN "direction" VARCHAR(255) DEFAULT NULL; \ No newline at end of file diff --git a/persistence/src/main/resources/db/migration/observatory/V4_0__add_direction.sql b/persistence/src/main/resources/db/migration/observatory/V4_0__add_direction.sql new file mode 100644 index 0000000..b9ed63b --- /dev/null +++ b/persistence/src/main/resources/db/migration/observatory/V4_0__add_direction.sql @@ -0,0 +1,2 @@ +ALTER TABLE "observation_job" + ADD COLUMN "direction" VARCHAR(255) DEFAULT NULL; \ No newline at end of file diff --git a/service/src/main/java/de/starwit/service/analytics/MetadataService.java b/service/src/main/java/de/starwit/service/analytics/MetadataService.java index 73f0584..7bb5b59 100644 --- a/service/src/main/java/de/starwit/service/analytics/MetadataService.java +++ b/service/src/main/java/de/starwit/service/analytics/MetadataService.java @@ -38,6 +38,7 @@ public MetadataEntity saveMetadataForJob(ObservationJobEntity jobEntity) { metadata.setCenterLatitude(jobEntity.getCenterLatitude()); metadata.setCenterLongitude(jobEntity.getCenterLongitude()); metadata.setObservationAreaId(jobEntity.getObservationAreaId()); + metadata.setDirection(jobEntity.getDirection()); List coordinates = new ArrayList<>(); if (jobEntity.getGeoReferenced()) { diff --git a/service/src/main/java/de/starwit/service/observatory/ObservationJobService.java b/service/src/main/java/de/starwit/service/observatory/ObservationJobService.java index 81537d8..7f7760a 100644 --- a/service/src/main/java/de/starwit/service/observatory/ObservationJobService.java +++ b/service/src/main/java/de/starwit/service/observatory/ObservationJobService.java @@ -96,6 +96,7 @@ public ObservationJobEntity update(Long id, ObservationJobEntity jobUpdate) { existingJob.setGeometryPoints(jobUpdate.getGeometryPoints()); existingJob.setCenterLatitude(jobUpdate.getCenterLatitude()); existingJob.setCenterLongitude(jobUpdate.getCenterLongitude()); + existingJob.setDirection(jobUpdate.getDirection()); ObservationJobEntity updatedJob = observationJobRepository.save(existingJob); From 9516a9ff5ee5bea1b04cc285e0e08075050d3cdd Mon Sep 17 00:00:00 2001 From: flonix8 Date: Wed, 4 Mar 2026 09:19:06 +0100 Subject: [PATCH 2/6] Change metadata query to yield latest metadata set --- .../analytics/repository/MetadataRepository.java | 2 ++ .../java/de/starwit/service/analytics/MetadataService.java | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/persistence/src/main/java/de/starwit/persistence/analytics/repository/MetadataRepository.java b/persistence/src/main/java/de/starwit/persistence/analytics/repository/MetadataRepository.java index 9905713..bf38c87 100644 --- a/persistence/src/main/java/de/starwit/persistence/analytics/repository/MetadataRepository.java +++ b/persistence/src/main/java/de/starwit/persistence/analytics/repository/MetadataRepository.java @@ -12,4 +12,6 @@ public interface MetadataRepository extends JpaRepository public MetadataEntity findFirstByNameAndClassification(String name, String classification); + public MetadataEntity findFirstByNameAndClassificationOrderByIdDesc(String name, String classification); + } diff --git a/service/src/main/java/de/starwit/service/analytics/MetadataService.java b/service/src/main/java/de/starwit/service/analytics/MetadataService.java index 7bb5b59..52f48ef 100644 --- a/service/src/main/java/de/starwit/service/analytics/MetadataService.java +++ b/service/src/main/java/de/starwit/service/analytics/MetadataService.java @@ -28,7 +28,7 @@ public MetadataRepository getRepository() { public MetadataEntity saveMetadataForJob(ObservationJobEntity jobEntity) { - MetadataEntity metadata = metadataRepository.findFirstByNameAndClassification(jobEntity.getName(), jobEntity.getClassification()); + MetadataEntity metadata = findCurrentMetadata(jobEntity); if (metadata == null) { metadata = new MetadataEntity(); @@ -69,5 +69,9 @@ public MetadataEntity findFirstByNameAndClassification(String name, String class MetadataEntity metadata = metadataRepository.findFirstByNameAndClassification(name, classification); return metadata; } + + public MetadataEntity findCurrentMetadata(ObservationJobEntity jobEntity) { + return metadataRepository.findFirstByNameAndClassificationOrderByIdDesc(jobEntity.getName(), jobEntity.getClassification()); + } } From 60e82bc5b70913d081df0336c1cf4035d947ed7e Mon Sep 17 00:00:00 2001 From: flonix8 Date: Thu, 5 Mar 2026 10:17:15 +0100 Subject: [PATCH 3/6] Drop uniqueness constraint for metadata table; Check if metadata needs to be updated by diffing --- ...4_0__remove_unique_metadata_constraint.sql | 1 + .../service/analytics/MetadataService.java | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 persistence/src/main/resources/db/migration/analytics/V4_0__remove_unique_metadata_constraint.sql diff --git a/persistence/src/main/resources/db/migration/analytics/V4_0__remove_unique_metadata_constraint.sql b/persistence/src/main/resources/db/migration/analytics/V4_0__remove_unique_metadata_constraint.sql new file mode 100644 index 0000000..b545e43 --- /dev/null +++ b/persistence/src/main/resources/db/migration/analytics/V4_0__remove_unique_metadata_constraint.sql @@ -0,0 +1 @@ +ALTER TABLE "metadata" DROP CONSTRAINT "unique_name_classification"; \ No newline at end of file diff --git a/service/src/main/java/de/starwit/service/analytics/MetadataService.java b/service/src/main/java/de/starwit/service/analytics/MetadataService.java index 52f48ef..476ecb3 100644 --- a/service/src/main/java/de/starwit/service/analytics/MetadataService.java +++ b/service/src/main/java/de/starwit/service/analytics/MetadataService.java @@ -10,6 +10,7 @@ import de.starwit.persistence.analytics.entity.MetadataEntity; import de.starwit.persistence.analytics.repository.MetadataRepository; import de.starwit.persistence.observatory.entity.ObservationJobEntity; +import de.starwit.persistence.observatory.entity.PointEntity; import de.starwit.service.impl.ServiceInterface; @Service @@ -71,7 +72,35 @@ public MetadataEntity findFirstByNameAndClassification(String name, String class } public MetadataEntity findCurrentMetadata(ObservationJobEntity jobEntity) { - return metadataRepository.findFirstByNameAndClassificationOrderByIdDesc(jobEntity.getName(), jobEntity.getClassification()); + MetadataEntity latestMetadata = metadataRepository.findFirstByNameAndClassificationOrderByIdDesc(jobEntity.getName(), jobEntity.getClassification()); + if (latestMetadata != null && metadataMatchesJob(latestMetadata, jobEntity)) { + return latestMetadata; + } else { + return null; + } + } + + /** + * Checks if all metadata fields equal the corresponding job fields (i.e. whether given metadata entity belongs to the given job) + */ + private boolean metadataMatchesJob(MetadataEntity metadata, ObservationJobEntity job) { + if (!metadata.getName().equals(job.getName())) return false; + if (!metadata.getClassification().equals(job.getClassification())) return false; + if (metadata.getGeoReferenced() != job.getGeoReferenced()) return false; + if (!metadata.getCenterLatitude().equals(job.getCenterLatitude())) return false; + if (!metadata.getCenterLongitude().equals(job.getCenterLongitude())) return false; + if (metadata.getObservationAreaId() != job.getObservationAreaId()) return false; + if (!metadata.getDirection().equals(job.getDirection())) return false; + if (job.getGeoReferenced()) { + for (int i = 0; i < metadata.getGeometryCoordinates().size(); i++) { + CoordinateEntity c1 = metadata.getGeometryCoordinates().get(i); + PointEntity c2 = job.getGeometryPoints().get(i); + if (!c1.getLatitude().equals(c2.getLatitude())) return false; + if (!c1.getLongitude().equals(c2.getLongitude())) return false; + } + } + + return true; } } From 949ef0805d96b7bfa001bcf0f7166e564dc70c9f Mon Sep 17 00:00:00 2001 From: flonix8 Date: Fri, 6 Mar 2026 16:29:03 +0100 Subject: [PATCH 4/6] Fix direction handling if null --- .../main/java/de/starwit/service/analytics/MetadataService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/src/main/java/de/starwit/service/analytics/MetadataService.java b/service/src/main/java/de/starwit/service/analytics/MetadataService.java index 476ecb3..e32809a 100644 --- a/service/src/main/java/de/starwit/service/analytics/MetadataService.java +++ b/service/src/main/java/de/starwit/service/analytics/MetadataService.java @@ -90,7 +90,7 @@ private boolean metadataMatchesJob(MetadataEntity metadata, ObservationJobEntity if (!metadata.getCenterLatitude().equals(job.getCenterLatitude())) return false; if (!metadata.getCenterLongitude().equals(job.getCenterLongitude())) return false; if (metadata.getObservationAreaId() != job.getObservationAreaId()) return false; - if (!metadata.getDirection().equals(job.getDirection())) return false; + if (metadata.getDirection() != null && !metadata.getDirection().equals(job.getDirection())) return false; if (job.getGeoReferenced()) { for (int i = 0; i < metadata.getGeometryCoordinates().size(); i++) { CoordinateEntity c1 = metadata.getGeometryCoordinates().get(i); From 98f5a1229a41ae60751e16465320442be26b6bd1 Mon Sep 17 00:00:00 2001 From: flonix8 Date: Tue, 10 Mar 2026 09:20:38 +0100 Subject: [PATCH 5/6] Fix metadata equality check --- .../service/analytics/MetadataService.java | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/service/src/main/java/de/starwit/service/analytics/MetadataService.java b/service/src/main/java/de/starwit/service/analytics/MetadataService.java index e32809a..08b86aa 100644 --- a/service/src/main/java/de/starwit/service/analytics/MetadataService.java +++ b/service/src/main/java/de/starwit/service/analytics/MetadataService.java @@ -84,19 +84,21 @@ public MetadataEntity findCurrentMetadata(ObservationJobEntity jobEntity) { * Checks if all metadata fields equal the corresponding job fields (i.e. whether given metadata entity belongs to the given job) */ private boolean metadataMatchesJob(MetadataEntity metadata, ObservationJobEntity job) { - if (!metadata.getName().equals(job.getName())) return false; - if (!metadata.getClassification().equals(job.getClassification())) return false; - if (metadata.getGeoReferenced() != job.getGeoReferenced()) return false; - if (!metadata.getCenterLatitude().equals(job.getCenterLatitude())) return false; - if (!metadata.getCenterLongitude().equals(job.getCenterLongitude())) return false; - if (metadata.getObservationAreaId() != job.getObservationAreaId()) return false; - if (metadata.getDirection() != null && !metadata.getDirection().equals(job.getDirection())) return false; + if (metadata.getName() != null && !metadata.getName().equals(job.getName())) return false; + if (metadata.getClassification() != null && !metadata.getClassification().equals(job.getClassification())) return false; + if (metadata.getGeoReferenced() != null && !metadata.getGeoReferenced().equals(job.getGeoReferenced())) return false; + if (metadata.getCenterLatitude() != null && !metadata.getCenterLatitude().equals(job.getCenterLatitude())) return false; + if (metadata.getCenterLongitude() != null && !metadata.getCenterLongitude().equals(job.getCenterLongitude())) return false; + if (metadata.getObservationAreaId() != null && !metadata.getObservationAreaId().equals(job.getObservationAreaId())) return false; + if (metadata.getDirection() != null && !metadata.getDirection().equals(job.getDirection())) return false; + + // Check if geometry matches (only if geoReferenced is true, otherwise geometry is not relevant and can be ignored) if (job.getGeoReferenced()) { for (int i = 0; i < metadata.getGeometryCoordinates().size(); i++) { CoordinateEntity c1 = metadata.getGeometryCoordinates().get(i); PointEntity c2 = job.getGeometryPoints().get(i); - if (!c1.getLatitude().equals(c2.getLatitude())) return false; - if (!c1.getLongitude().equals(c2.getLongitude())) return false; + if (c1.getLatitude() != null && !c1.getLatitude().equals(c2.getLatitude())) return false; + if (c1.getLongitude() != null && !c1.getLongitude().equals(c2.getLongitude())) return false; } } From 6fc19852ffeeb43482afa228223e8f54a1412aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anett=20H=C3=BCbner?= Date: Thu, 12 Mar 2026 13:12:34 +0100 Subject: [PATCH 6/6] corrected metadata refreshing --- .../service/analytics/MetadataService.java | 55 +++++++++++++------ 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/service/src/main/java/de/starwit/service/analytics/MetadataService.java b/service/src/main/java/de/starwit/service/analytics/MetadataService.java index 08b86aa..2415f90 100644 --- a/service/src/main/java/de/starwit/service/analytics/MetadataService.java +++ b/service/src/main/java/de/starwit/service/analytics/MetadataService.java @@ -28,7 +28,7 @@ public MetadataRepository getRepository() { } public MetadataEntity saveMetadataForJob(ObservationJobEntity jobEntity) { - + MetadataEntity metadata = findCurrentMetadata(jobEntity); if (metadata == null) { @@ -49,7 +49,7 @@ public MetadataEntity saveMetadataForJob(ObservationJobEntity jobEntity) { } } metadata.setGeometryCoordinates(coordinates); - + metadata = metadataRepository.saveAndFlush(metadata); } @@ -72,7 +72,8 @@ public MetadataEntity findFirstByNameAndClassification(String name, String class } public MetadataEntity findCurrentMetadata(ObservationJobEntity jobEntity) { - MetadataEntity latestMetadata = metadataRepository.findFirstByNameAndClassificationOrderByIdDesc(jobEntity.getName(), jobEntity.getClassification()); + MetadataEntity latestMetadata = metadataRepository + .findFirstByNameAndClassificationOrderByIdDesc(jobEntity.getName(), jobEntity.getClassification()); if (latestMetadata != null && metadataMatchesJob(latestMetadata, jobEntity)) { return latestMetadata; } else { @@ -81,28 +82,46 @@ public MetadataEntity findCurrentMetadata(ObservationJobEntity jobEntity) { } /** - * Checks if all metadata fields equal the corresponding job fields (i.e. whether given metadata entity belongs to the given job) + * Checks if all metadata fields equal the corresponding job fields (i.e. + * whether given metadata entity belongs to the given job) */ private boolean metadataMatchesJob(MetadataEntity metadata, ObservationJobEntity job) { - if (metadata.getName() != null && !metadata.getName().equals(job.getName())) return false; - if (metadata.getClassification() != null && !metadata.getClassification().equals(job.getClassification())) return false; - if (metadata.getGeoReferenced() != null && !metadata.getGeoReferenced().equals(job.getGeoReferenced())) return false; - if (metadata.getCenterLatitude() != null && !metadata.getCenterLatitude().equals(job.getCenterLatitude())) return false; - if (metadata.getCenterLongitude() != null && !metadata.getCenterLongitude().equals(job.getCenterLongitude())) return false; - if (metadata.getObservationAreaId() != null && !metadata.getObservationAreaId().equals(job.getObservationAreaId())) return false; - if (metadata.getDirection() != null && !metadata.getDirection().equals(job.getDirection())) return false; - - // Check if geometry matches (only if geoReferenced is true, otherwise geometry is not relevant and can be ignored) - if (job.getGeoReferenced()) { + boolean matches = true; + + matches = matches && metadata.getName().equals(job.getName()); + matches = matches && (metadata.getClassification() == null && job.getClassification() == null + || job.getClassification() != null && job.getClassification().equals(metadata.getClassification())); + + matches = matches && (metadata.getGeoReferenced() == null && job.getGeoReferenced() == null + || job.getGeoReferenced() != null && job.getGeoReferenced().equals(metadata.getGeoReferenced())); + + matches = matches && (metadata.getCenterLatitude() == null && job.getCenterLatitude() == null + || job.getCenterLatitude() != null && job.getCenterLatitude().equals(metadata.getCenterLatitude())); + + matches = matches && (metadata.getCenterLongitude() == null && job.getCenterLongitude() == null + || job.getCenterLongitude() != null && job.getCenterLongitude().equals(metadata.getCenterLongitude())); + + matches = matches && (metadata.getObservationAreaId() == null && job.getObservationAreaId() == null + || job.getObservationAreaId() != null + && job.getObservationAreaId().equals(metadata.getObservationAreaId())); + + matches = matches && (metadata.getDirection() == null && job.getDirection() == null + || job.getDirection() != null && job.getDirection().equals(metadata.getDirection())); + + // Check if geometry matches (only if geoReferenced is true, otherwise geometry + // is not relevant and can be ignored) + if (matches && job.getGeoReferenced()) { for (int i = 0; i < metadata.getGeometryCoordinates().size(); i++) { CoordinateEntity c1 = metadata.getGeometryCoordinates().get(i); PointEntity c2 = job.getGeometryPoints().get(i); - if (c1.getLatitude() != null && !c1.getLatitude().equals(c2.getLatitude())) return false; - if (c1.getLongitude() != null && !c1.getLongitude().equals(c2.getLongitude())) return false; + if (c1.getLatitude() != null && !c1.getLatitude().equals(c2.getLatitude())) + return false; + if (c1.getLongitude() != null && !c1.getLongitude().equals(c2.getLongitude())) + return false; } } - return true; + return matches; } - + }