1 package de.dlr.shepard.data.spatialdata.repositories;
2
3 import static org.junit.jupiter.api.Assertions.assertEquals;
4 import static org.junit.jupiter.api.Assertions.assertFalse;
5 import static org.junit.jupiter.api.Assertions.assertNotNull;
6 import static org.junit.jupiter.api.Assertions.assertTrue;
7
8 import de.dlr.shepard.data.spatialdata.io.FilterCondition;
9 import de.dlr.shepard.data.spatialdata.io.Operator;
10 import de.dlr.shepard.data.spatialdata.model.GeometryBuilder;
11 import de.dlr.shepard.data.spatialdata.model.SpatialDataPoint;
12 import io.quarkus.logging.Log;
13 import io.quarkus.test.junit.QuarkusTest;
14 import jakarta.enterprise.context.control.ActivateRequestContext;
15 import jakarta.inject.Inject;
16 import jakarta.transaction.Transactional;
17 import java.time.Instant;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 import org.junit.jupiter.api.AfterAll;
25 import org.junit.jupiter.api.BeforeAll;
26 import org.junit.jupiter.api.Test;
27 import org.junit.jupiter.api.TestInstance;
28 import org.locationtech.jts.geom.Coordinate;
29
30 @QuarkusTest
31 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
32 @ActivateRequestContext
33 public class SpatialDataPointRepositoryTest {
34
35 @Inject
36 SpatialDataPointRepository repository;
37
38 Long movingTimeStamp = Instant.now().toEpochMilli() * 1_000_000;
39 final Long testContainerId = 987651L;
40 final int numberOfTestPoints = 100;
41 final ArrayList<SpatialDataPoint> testDataPoints = new ArrayList<SpatialDataPoint>();
42 private ArrayList<Long> containerIdsForCleanup = new ArrayList<Long>();
43
44 private long generateManagedContainerId() {
45 var id = 0L;
46 do {
47 id = (long) (Math.random() * 1_000);
48 } while (containerIdsForCleanup.contains(id));
49
50 containerIdsForCleanup.add(id);
51 return id;
52 }
53
54 @BeforeAll
55 @Transactional
56 public void setup() {
57 containerIdsForCleanup.add(testContainerId);
58 for (var i = 0; i < numberOfTestPoints; i++) {
59 testDataPoints.add(
60 new SpatialDataPoint(
61 testContainerId,
62 generateTimestamp(),
63 GeometryBuilder.fromCoordinate(new Coordinate(i, i, i)),
64 Map.of("a_meta_data", "metadata_%s".formatted(i)),
65 Map.of("a_measurement", i)
66 )
67 );
68 }
69 repository.insert(testContainerId, testDataPoints.toArray(new SpatialDataPoint[0]));
70 }
71
72 @AfterAll
73 @Transactional
74 public void teardown() {
75 containerIdsForCleanup.stream().forEach(id -> repository.deleteByContainerId(id));
76 }
77
78 @Test
79 @Transactional
80 public void insert_dataWithMetadataAndMeasurements_allPropertiesStored() {
81 var containerId = generateManagedContainerId();
82 var timestamp = 1_000_000_000_000L;
83 var geometry = GeometryBuilder.fromCoordinate(new Coordinate(4, 5, 6));
84
85 Map<String, Object> metadata = new HashMap<>();
86 metadata.put("intValue", 1);
87 metadata.put("floatValue", 1.2345);
88 metadata.put("stringValue", "hello world");
89
90 Map<String, Object> measurements = new HashMap<>();
91 measurements.put("a", 1);
92 measurements.put("b", 1.2345);
93 measurements.put("c", "{\"key\":\"value\"}");
94
95 var dataPoint = new SpatialDataPoint(containerId, timestamp, geometry, metadata, measurements);
96
97 var result = repository.insert(containerId, dataPoint);
98 assertEquals(1, result);
99
100 var current = repository.getByContainerId(containerId);
101 assertEquals(1, current.size());
102 assertEquals(1_000_000_000_000L, current.get(0).getTime());
103 assertEquals("org.locationtech.jts.geom.Point", current.get(0).getPosition().getClass().getName());
104 assertEquals(4, current.get(0).getPosition().getCoordinate().x);
105 assertEquals(5, current.get(0).getPosition().getCoordinate().y);
106 assertEquals(6, current.get(0).getPosition().getCoordinate().z);
107 assertEquals(metadata, current.get(0).getMetadata());
108 assertEquals(measurements, current.get(0).getMeasurements());
109 }
110
111 @Test
112 @Transactional
113 public void insert_multiplePoints_success() {
114 final ArrayList<SpatialDataPoint> entryList = new ArrayList<SpatialDataPoint>();
115 var containerId = generateManagedContainerId();
116
117 for (var i = 0; i < 100; i++) {
118 entryList.add(
119 new SpatialDataPoint(
120 containerId,
121 generateTimestamp(),
122 GeometryBuilder.fromCoordinate(new Coordinate(i, i, i)),
123 null,
124 null
125 )
126 );
127 }
128
129 var result = repository.insert(containerId, entryList.toArray(new SpatialDataPoint[0]));
130 assertEquals(100, result);
131
132 var current = repository.getByContainerId(containerId);
133 assertEquals(100, current.size());
134 assertFalse(Double.isNaN(current.get(0).getPosition().getCoordinate().x));
135 assertFalse(Double.isNaN(current.get(0).getPosition().getCoordinate().y));
136 assertFalse(Double.isNaN(current.get(0).getPosition().getCoordinate().z));
137 }
138
139 @Test
140 public void getWithoutGeometryFilter_returnsAllData_success() {
141 var expected = repository.getByContainerId(testContainerId);
142 var actual = repository.get(
143 testContainerId,
144 -1L,
145 Instant.now().toEpochMilli() * 1_000_000 + 1000,
146 Collections.emptyMap(),
147 Collections.emptyList(),
148 null,
149 null
150 );
151 assertEquals(expected, actual);
152 }
153
154 @Test
155 public void getWithoutGeometryFilter_returnsLimitData_success() {
156 var actual = repository.get(
157 testContainerId,
158 -1L,
159 Instant.now().toEpochMilli() * 1_000_000 + 1000,
160 Collections.emptyMap(),
161 Collections.emptyList(),
162 3,
163 null
164 );
165 assertEquals(3, actual.size());
166 }
167
168 @Test
169 public void getWithoutGeometryFilter_returnsSkippedData_success() {
170 var actual = repository.get(testContainerId, null, null, Collections.emptyMap(), Collections.emptyList(), null, 10);
171 assertEquals(10, actual.size());
172 }
173
174 @Test
175 public void getWithoutGeometryFilter_returnsFilteredData_success() {
176 var expected = List.of(testDataPoints.get(1));
177 var actual = repository.get(
178 testContainerId,
179 -1L,
180 Instant.now().toEpochMilli() * 1_000_000 + 1000,
181 Map.of("a_meta_data", "metadata_1"),
182 List.of(new FilterCondition("a_measurement", Operator.EQUALS, 1)),
183 null,
184 null
185 );
186
187 assertEquals(expected, actual);
188 }
189
190
191 @Test
192 public void getByBoundingBox_returnsAllData_success() {
193 var data = repository.getByBoundingBox(
194 testContainerId,
195 new Coordinate(0, 0, 0),
196 new Coordinate(9999, 9999, 9999),
197 null,
198 null,
199 Collections.emptyMap(),
200 Collections.emptyList(),
201 null,
202 null
203 );
204
205 assertNotNull(data);
206 assertTrue(data.size() == numberOfTestPoints);
207 }
208
209 @Test
210 @Transactional
211 public void getByBoundingBox_returnsSomeData_success() {
212 var containerId = generateManagedContainerId();
213
214 var dataPoint1 = new SpatialDataPoint(
215 containerId,
216 generateTimestamp(),
217 GeometryBuilder.fromCoordinate(new Coordinate(666, 666, 666)),
218 null,
219 null
220 );
221 var dataPoint2 = new SpatialDataPoint(
222 containerId,
223 generateTimestamp(),
224 GeometryBuilder.fromCoordinate(new Coordinate(600, 666, 600)),
225 null,
226 null
227 );
228 var dataPoint3 = new SpatialDataPoint(
229 containerId,
230 generateTimestamp(),
231 GeometryBuilder.fromCoordinate(new Coordinate(666, 700, 666)),
232 null,
233 null
234 );
235 var dataPoint4 = new SpatialDataPoint(
236 containerId,
237 generateTimestamp(),
238 GeometryBuilder.fromCoordinate(new Coordinate(700, 700, 700)),
239 null,
240 null
241 );
242 var dataPoints = new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4 };
243 var result = repository.insert(containerId, dataPoints);
244
245 var data = repository.getByBoundingBox(
246 containerId,
247 new Coordinate(500, 500, 500),
248 new Coordinate(700, 700, 700),
249 null,
250 null,
251 Collections.emptyMap(),
252 Collections.emptyList(),
253 null,
254 null
255 );
256
257 assertNotNull(data);
258 assertEquals(4, result);
259 assertEquals(4, data.size());
260
261 Arrays.stream(dataPoints).forEach(dataPoint -> assertTrue(data.contains(dataPoint)));
262 }
263
264 @Test
265 @Transactional
266 public void getByBoundingBox_returnsSomeData_withLimit_success() {
267 var containerId = generateManagedContainerId();
268
269 var dataPoint1 = new SpatialDataPoint(
270 containerId,
271 generateTimestamp(),
272 GeometryBuilder.fromCoordinate(new Coordinate(866, 866, 866)),
273 null,
274 null
275 );
276 var dataPoint2 = new SpatialDataPoint(
277 containerId,
278 generateTimestamp(),
279 GeometryBuilder.fromCoordinate(new Coordinate(800, 866, 800)),
280 null,
281 null
282 );
283 var dataPoint3 = new SpatialDataPoint(
284 containerId,
285 generateTimestamp(),
286 GeometryBuilder.fromCoordinate(new Coordinate(866, 900, 866)),
287 null,
288 null
289 );
290 var dataPoint4 = new SpatialDataPoint(
291 containerId,
292 generateTimestamp(),
293 GeometryBuilder.fromCoordinate(new Coordinate(900, 900, 900)),
294 null,
295 null
296 );
297 var result = repository.insert(
298 containerId,
299 new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4 }
300 );
301
302 var data = repository.getByBoundingBox(
303 containerId,
304 new Coordinate(700, 700, 700),
305 new Coordinate(900, 900, 900),
306 null,
307 null,
308 Collections.emptyMap(),
309 Collections.emptyList(),
310 3,
311 null
312 );
313
314 assertNotNull(data);
315 assertEquals(4, result);
316 assertEquals(3, data.size());
317 }
318
319 @Test
320 @Transactional
321 public void getByBoundingBox_returnsSomeData_withSkip_success() {
322 var containerId = generateManagedContainerId();
323
324 var dataPoint1 = new SpatialDataPoint(
325 containerId,
326 generateTimestamp(),
327 GeometryBuilder.fromCoordinate(new Coordinate(766, 766, 766)),
328 null,
329 null
330 );
331 var dataPoint2 = new SpatialDataPoint(
332 containerId,
333 generateTimestamp(),
334 GeometryBuilder.fromCoordinate(new Coordinate(700, 766, 700)),
335 null,
336 null
337 );
338 var dataPoint3 = new SpatialDataPoint(
339 containerId,
340 generateTimestamp(),
341 GeometryBuilder.fromCoordinate(new Coordinate(766, 700, 766)),
342 null,
343 null
344 );
345 var dataPoint4 = new SpatialDataPoint(
346 containerId,
347 generateTimestamp(),
348 GeometryBuilder.fromCoordinate(new Coordinate(700, 700, 700)),
349 null,
350 null
351 );
352 var result = repository.insert(
353 containerId,
354 new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4 }
355 );
356
357 var data = repository.getByBoundingBox(
358 containerId,
359 new Coordinate(700, 700, 700),
360 new Coordinate(800, 800, 800),
361 null,
362 null,
363 Collections.emptyMap(),
364 Collections.emptyList(),
365 null,
366 2
367 );
368
369 assertNotNull(data);
370 assertEquals(4, result);
371 assertEquals(2, data.size());
372 }
373
374 @Test
375 public void getByBoundingBox_returnsNoData_success() {
376 var data = repository.getByBoundingBox(
377 testContainerId,
378 new Coordinate(-1, -1, -1),
379 new Coordinate(-10, -10, -10),
380 null,
381 null,
382 Collections.emptyMap(),
383 Collections.emptyList(),
384 null,
385 null
386 );
387
388 assertNotNull(data);
389 assertEquals(0, data.size());
390 }
391
392
393 @Test
394 public void getByBoundingSphere_returnsAllData_success() {
395 var data = repository.getByBoundingSphere(
396 testContainerId,
397 new Coordinate(0, 0, 0),
398 9999,
399 null,
400 null,
401 Collections.emptyMap(),
402 Collections.emptyList(),
403 null,
404 null
405 );
406
407 assertNotNull(data);
408 assertTrue(data.size() == numberOfTestPoints);
409 }
410
411 @Test
412 @Transactional
413 public void getByBoundingSphere_returnsSomeData_success() {
414 var containerId = generateManagedContainerId();
415 var dataPoint1 = new SpatialDataPoint(
416 containerId,
417 generateTimestamp(),
418 GeometryBuilder.fromCoordinate(new Coordinate(1666, 1666, 1666)),
419 null,
420 null
421 );
422 var dataPoint2 = new SpatialDataPoint(
423 containerId,
424 generateTimestamp(),
425 GeometryBuilder.fromCoordinate(new Coordinate(1600, 1666, 1600)),
426 null,
427 null
428 );
429 var dataPoint3 = new SpatialDataPoint(
430 containerId,
431 generateTimestamp(),
432 GeometryBuilder.fromCoordinate(new Coordinate(1666, 1700, 1666)),
433 null,
434 null
435 );
436 var dataPoint4 = new SpatialDataPoint(
437 containerId,
438 generateTimestamp(),
439 GeometryBuilder.fromCoordinate(new Coordinate(1700, 1700, 1700)),
440 null,
441 null
442 );
443 var dataPoint5 = new SpatialDataPoint(
444 containerId,
445 generateTimestamp(),
446 GeometryBuilder.fromCoordinate(new Coordinate(1800, 1800, 1800)),
447 null,
448 null
449 );
450 var dataPoints = new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4, dataPoint5 };
451 var result = repository.insert(containerId, dataPoints);
452
453 var data = repository.getByBoundingSphere(
454 containerId,
455 new Coordinate(1666, 1666, 1666),
456 100,
457 null,
458 null,
459 Collections.emptyMap(),
460 Collections.emptyList(),
461 null,
462 null
463 );
464
465 assertNotNull(data);
466 assertEquals(5, result);
467 assertEquals(4, data.size());
468 dataPoints = new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4 };
469 Arrays.stream(dataPoints).forEach(dataPoint -> assertTrue(data.contains(dataPoint)));
470 }
471
472 @Test
473 @Transactional
474 public void getByBoundingSphere_returnsData_withLIMIT_success() {
475 var containerId = generateManagedContainerId();
476 var dataPoint1 = new SpatialDataPoint(
477 containerId,
478 generateTimestamp(),
479 GeometryBuilder.fromCoordinate(new Coordinate(1666, 1666, 1666)),
480 null,
481 null
482 );
483 var dataPoint2 = new SpatialDataPoint(
484 containerId,
485 generateTimestamp(),
486 GeometryBuilder.fromCoordinate(new Coordinate(1600, 1666, 1600)),
487 null,
488 null
489 );
490 var dataPoint3 = new SpatialDataPoint(
491 containerId,
492 generateTimestamp(),
493 GeometryBuilder.fromCoordinate(new Coordinate(1666, 1700, 1666)),
494 null,
495 null
496 );
497 var dataPoint4 = new SpatialDataPoint(
498 containerId,
499 generateTimestamp(),
500 GeometryBuilder.fromCoordinate(new Coordinate(1700, 1700, 1700)),
501 null,
502 null
503 );
504 var dataPoint5 = new SpatialDataPoint(
505 containerId,
506 generateTimestamp(),
507 GeometryBuilder.fromCoordinate(new Coordinate(1800, 1800, 1800)),
508 null,
509 null
510 );
511 var result = repository.insert(
512 containerId,
513 new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4, dataPoint5 }
514 );
515
516 var data = repository.getByBoundingSphere(
517 containerId,
518 new Coordinate(1666, 1666, 1666),
519 100,
520 null,
521 null,
522 Collections.emptyMap(),
523 Collections.emptyList(),
524 3,
525 null
526 );
527
528 assertNotNull(data);
529 assertEquals(5, result);
530 assertEquals(3, data.size());
531 }
532
533 @Test
534 @Transactional
535 public void getByBoundingSphere_returnsData_withSkip_success() {
536 var containerId = generateManagedContainerId();
537 var dataPoint1 = new SpatialDataPoint(
538 containerId,
539 generateTimestamp(),
540 GeometryBuilder.fromCoordinate(new Coordinate(3980, 20, 10)),
541 null,
542 null
543 );
544 var dataPoint2 = new SpatialDataPoint(
545 containerId,
546 generateTimestamp(),
547 GeometryBuilder.fromCoordinate(new Coordinate(4020, -15, 5)),
548 null,
549 null
550 );
551 var dataPoint3 = new SpatialDataPoint(
552 containerId,
553 generateTimestamp(),
554 GeometryBuilder.fromCoordinate(new Coordinate(4010, 25, -30)),
555 null,
556 null
557 );
558 var dataPoint4 = new SpatialDataPoint(
559 containerId,
560 generateTimestamp(),
561 GeometryBuilder.fromCoordinate(new Coordinate(3995, -35, 40)),
562 null,
563 null
564 );
565 var dataPoint5 = new SpatialDataPoint(
566 containerId,
567 generateTimestamp(),
568 GeometryBuilder.fromCoordinate(new Coordinate(4000, 10, -50)),
569 null,
570 null
571 );
572 var dataPoint6 = new SpatialDataPoint(
573 containerId,
574 generateTimestamp(),
575 GeometryBuilder.fromCoordinate(new Coordinate(4005, 0, -40)),
576 null,
577 null
578 );
579 var result = repository.insert(
580 containerId,
581 new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4, dataPoint5, dataPoint6 }
582 );
583
584 var data = repository.getByBoundingSphere(
585 containerId,
586 new Coordinate(4000, 0, 0),
587 100,
588 null,
589 null,
590 Collections.emptyMap(),
591 Collections.emptyList(),
592 null,
593 2
594 );
595
596 assertNotNull(data);
597 assertEquals(6, result);
598 assertEquals(3, data.size());
599 }
600
601 @Test
602 public void getByBoundingSphere_returnsNoData_success() {
603 var data = repository.getByBoundingSphere(
604 testContainerId,
605 new Coordinate(-10, -10, -10),
606 1,
607 null,
608 null,
609 Collections.emptyMap(),
610 Collections.emptyList(),
611 null,
612 null
613 );
614
615 assertNotNull(data);
616 assertEquals(0, data.size());
617 }
618
619
620 @Test
621 public void getByKNN_returnsAllData_success() {
622 var data = repository.getByKNN(
623 testContainerId,
624 new Coordinate(0, 0, 0),
625 9999,
626 null,
627 null,
628 Collections.emptyMap(),
629 Collections.emptyList()
630 );
631
632 assertNotNull(data);
633 assertTrue(data.size() == numberOfTestPoints);
634 }
635
636 @Test
637 public void getByKNN_returnsSomeData_success() {
638 var data = repository.getByKNN(
639 testContainerId,
640 new Coordinate(4, 4, 4),
641 3,
642 null,
643 null,
644 Collections.emptyMap(),
645 Collections.emptyList()
646 );
647
648 assertNotNull(data);
649 assertEquals(3, data.size());
650
651
652 for (SpatialDataPoint entry : data) {
653 Log.info(entry.getPosition().getCoordinate());
654 final var xCoord = entry.getPosition().getCoordinate().x;
655 final var yCoord = entry.getPosition().getCoordinate().y;
656 final var zCoord = entry.getPosition().getCoordinate().z;
657 assertTrue(xCoord == 3 || xCoord == 5 || xCoord == 4);
658 assertTrue(yCoord == 3 || yCoord == 5 || yCoord == 4);
659 assertTrue(zCoord == 3 || zCoord == 5 || zCoord == 4);
660 }
661 }
662
663 @Test
664 public void getByKNN_returnsNoData_success() {
665 var data = repository.getByKNN(
666 testContainerId,
667 new Coordinate(-1, -1, -1),
668 0,
669 null,
670 null,
671 Collections.emptyMap(),
672 Collections.emptyList()
673 );
674
675 assertNotNull(data);
676 assertEquals(0, data.size());
677 }
678
679 @Test
680 @Transactional
681 public void deleteData_byContainerId_success() {
682 var containerId = generateManagedContainerId();
683 repository.insert(
684 containerId,
685 new SpatialDataPoint(containerId, generateTimestamp(), GeometryBuilder.fromXYZ(1, 1, 1), null, null)
686 );
687
688 int numberDeletedRows = repository.deleteByContainerId(containerId);
689 assertTrue(numberDeletedRows > 0);
690 }
691
692
693 @Test
694 @Transactional
695 public void insert_storeMetadataWithNestedObject_success() {
696 var containerId = generateManagedContainerId();
697
698 var nestedObject = new HashMap<String, Object>();
699 nestedObject.put("temperature", 23.4);
700 nestedObject.put("humidity", 0.6);
701 nestedObject.put("room", "living room");
702
703 Map<String, Object> metadata = new HashMap<>();
704 metadata.put("track", 1);
705 metadata.put("layer", 7);
706 metadata.put("floatValue", 1.2345);
707 metadata.put("stringValue", "hello world");
708 metadata.put("sensors", nestedObject);
709
710 var dataPoint = new SpatialDataPoint(
711 containerId,
712 generateTimestamp(),
713 GeometryBuilder.fromCoordinate(new Coordinate(1, 2, 3)),
714 metadata,
715 null
716 );
717 var result = repository.insert(containerId, dataPoint);
718 assertEquals(1, result);
719 }
720
721 @Test
722 @Transactional
723 public void getByBoundingBox_filterByMetadata_returnsOneRecord() {
724 var containerId = generateManagedContainerId();
725 var metadataFilter = new HashMap<String, Object>();
726 metadataFilter.put("layer", 7);
727 repository.insert(
728 containerId,
729 new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), metadataFilter, null)
730 );
731
732 var data = repository.getByBoundingBox(
733 containerId,
734 new Coordinate(0, 0, 0),
735 new Coordinate(2, 2, 2),
736 null,
737 null,
738 metadataFilter,
739 Collections.emptyList(),
740 null,
741 null
742 );
743
744 assertNotNull(data);
745 assertTrue(data.size() == 1);
746 }
747
748 @Test
749 @Transactional
750 public void getByKNN_filterByMetadata_returnsOneRecord() {
751 var containerId = generateManagedContainerId();
752 var metadataFilter = new HashMap<String, Object>();
753 metadataFilter.put("layer", 7);
754 var dataPoint = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), metadataFilter, null);
755 repository.insert(containerId, dataPoint);
756
757 var data = repository.getByKNN(
758 containerId,
759 new Coordinate(0, 0, 0),
760 1,
761 null,
762 null,
763 metadataFilter,
764 Collections.emptyList()
765 );
766
767 assertNotNull(data);
768 assertTrue(data.size() == 1);
769 assertTrue(data.get(0).equals(dataPoint));
770 }
771
772 @Test
773 @Transactional
774 public void getByKNN_filterByNestedMetadata_returnsOneRecord() {
775 var containerId = generateManagedContainerId();
776 var nestedObject = new HashMap<String, Object>();
777 nestedObject.put("temperature", 23.4);
778 nestedObject.put("humidity", 0.6);
779 nestedObject.put("room", "living room");
780
781 Map<String, Object> metadata = new HashMap<>();
782 metadata.put("track", 1);
783 metadata.put("layer", 7);
784 metadata.put("floatValue", 1.2345);
785 metadata.put("stringValue", "hello world");
786 metadata.put("sensors", nestedObject);
787 var dataPoint = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), metadata, null);
788 repository.insert(containerId, dataPoint);
789
790 var metadataFilter = new HashMap<String, Object>();
791 metadataFilter.put("layer", 7);
792 metadataFilter.put("sensors", Map.of("room", "living room", "humidity", 0.6));
793
794 var data = repository.getByKNN(
795 containerId,
796 new Coordinate(0, 0, 0),
797 1,
798 null,
799 null,
800 metadataFilter,
801 Collections.emptyList()
802 );
803
804 assertNotNull(data);
805 assertTrue(data.size() == 1);
806 assertTrue(data.get(0).equals(dataPoint));
807 }
808
809 @Test
810 @Transactional
811 public void getByKNN_filterByNestedMetadata_returnsNoData() {
812 var containerId = generateManagedContainerId();
813 var nestedObject = new HashMap<String, Object>();
814 nestedObject.put("temperature", 23.4);
815 nestedObject.put("humidity", 0.6);
816 nestedObject.put("room", "living room");
817
818 Map<String, Object> metadata = new HashMap<>();
819 metadata.put("track", 1);
820 metadata.put("layer", 7);
821 metadata.put("floatValue", 1.2345);
822 metadata.put("stringValue", "hello world");
823 metadata.put("sensors", nestedObject);
824 var dataPoint = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), metadata, null);
825 repository.insert(containerId, dataPoint);
826
827 var metadataFilter = new HashMap<String, Object>();
828 metadataFilter.put("layer", 7);
829 metadataFilter.put("sensors", Map.of("room", "dining room", "humidity", 0.6));
830
831 var data = repository.getByKNN(
832 containerId,
833 new Coordinate(0, 0, 0),
834 1,
835 null,
836 null,
837 metadataFilter,
838 Collections.emptyList()
839 );
840
841 assertNotNull(data);
842 assertTrue(data.size() == 0);
843 }
844
845 @Test
846 @Transactional
847 public void getByKNN_filterByTimestamp_returnsOneRecord() {
848 var containerId = generateManagedContainerId();
849 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), null, null);
850 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(1, 1, 1), null, null);
851 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2 });
852
853 var data = repository.getByKNN(
854 containerId,
855 new Coordinate(0, 0, 0),
856 1,
857 0l,
858 2l,
859 Collections.emptyMap(),
860 Collections.emptyList()
861 );
862
863 assertNotNull(data);
864 assertEquals(1, data.size());
865 assertEquals(dataPoint1, data.get(0));
866 }
867
868 @Test
869 @Transactional
870 public void getByKNN_filterByTimestamp_returnsNoData() {
871 var containerId = generateManagedContainerId();
872 repository.insert(containerId, new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), null, null));
873
874 var data = repository.getByKNN(
875 containerId,
876 new Coordinate(0, 0, 0),
877 1,
878 2l,
879 4l,
880 Collections.emptyMap(),
881 Collections.emptyList()
882 );
883
884 assertNotNull(data);
885 assertEquals(0, data.size());
886 }
887
888 @Test
889 @Transactional
890 public void getByKNN_filterByTimestampStart_returnsOneRecord() {
891 var containerId = generateManagedContainerId();
892 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), null, null);
893 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(10, 10, 10), null, null);
894 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2 });
895
896 var data = repository.getByKNN(
897 containerId,
898 new Coordinate(0, 0, 0),
899 1,
900 0l,
901 null,
902 Collections.emptyMap(),
903 Collections.emptyList()
904 );
905
906 assertNotNull(data);
907 assertEquals(1, data.size());
908 assertEquals(dataPoint1, data.get(0));
909 }
910
911 @Test
912 @Transactional
913 public void getByKNN_filterByTimestampEnd_returnsOneRecord() {
914 var containerId = generateManagedContainerId();
915 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), null, null);
916 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(1, 1, 1), null, null);
917 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2 });
918
919 var data = repository.getByKNN(
920 containerId,
921 new Coordinate(0, 0, 0),
922 1,
923 null,
924 2l,
925 Collections.emptyMap(),
926 Collections.emptyList()
927 );
928
929 assertNotNull(data);
930 assertEquals(1, data.size());
931 assertEquals(dataPoint1, data.get(0));
932 }
933
934 @Test
935 @Transactional
936 public void getByKNN_filterByMetadataAndTimestamp_returnsOneRecord() {
937 var containerId = generateManagedContainerId();
938 var metadata = new HashMap<String, Object>();
939 metadata.put("layer", 7);
940 metadata.put("track", 10);
941
942 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), metadata, null);
943 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(2, 2, 2), metadata, null);
944 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2 });
945
946 var metadataFilter = new HashMap<String, Object>();
947 metadataFilter.put("layer", 7);
948 var data = repository.getByKNN(
949 containerId,
950 new Coordinate(0, 0, 0),
951 1,
952 0L,
953 2L,
954 metadataFilter,
955 Collections.emptyList()
956 );
957
958 assertNotNull(data);
959 assertTrue(data.size() == 1);
960 assertTrue(data.get(0).equals(dataPoint1));
961 }
962
963 @Test
964 @Transactional
965 public void getByKNN_filterByMetadataAndTimestamp_returnsNoData() {
966 var containerId = generateManagedContainerId();
967 var metadata = new HashMap<String, Object>();
968 metadata.put("layer", 7);
969 metadata.put("track", 10);
970
971 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), metadata, null);
972 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(2, 2, 2), metadata, null);
973 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2 });
974
975 var metadataFilter = new HashMap<String, Object>();
976 metadataFilter.put("layer", 0);
977 var data = repository.getByKNN(
978 containerId,
979 new Coordinate(0, 0, 0),
980 1,
981 10L,
982 20L,
983 metadataFilter,
984 Collections.emptyList()
985 );
986
987 assertNotNull(data);
988 assertTrue(data.size() == 0);
989 }
990
991 @Test
992 @Transactional
993 public void getByKNN_filterByMeasurements_returnsOneRecord() {
994 var containerId = generateManagedContainerId();
995 var measurments = new HashMap<String, Object>();
996 var imageData = new HashMap<String, Object>();
997 imageData.put("format", "png");
998 imageData.put("size", 5000);
999 measurments.put("temperature", 7);
1000 measurments.put("pressure", 10);
1001 measurments.put("image", imageData);
1002
1003 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), null, measurments);
1004 imageData.put("size", 3000);
1005 measurments.put("image", imageData);
1006 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(2, 2, 2), null, measurments);
1007 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2 });
1008
1009 var measurementsFilter = List.of(
1010 new FilterCondition("image,size", Operator.LESS_THAN, 5000),
1011 new FilterCondition("image,size", Operator.GREATER_THAN, 2000),
1012 new FilterCondition("temperature", Operator.EQUALS, 7)
1013 );
1014 var data = repository.getByKNN(
1015 containerId,
1016 new Coordinate(0, 0, 0),
1017 1,
1018 null,
1019 null,
1020 Collections.emptyMap(),
1021 measurementsFilter
1022 );
1023
1024 assertNotNull(data);
1025 assertTrue(data.size() == 1);
1026 }
1027
1028 @Test
1029 @Transactional
1030 public void getByKNN_filterByMeasurements_returnsNoData() {
1031 var containerId = generateManagedContainerId();
1032 var measurments = new HashMap<String, Object>();
1033 var imageData = new HashMap<String, Object>();
1034 imageData.put("format", "png");
1035 imageData.put("size", 5000);
1036 measurments.put("temperature", 7);
1037 measurments.put("pressure", 10);
1038 measurments.put("image", imageData);
1039
1040 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), null, measurments);
1041 imageData.put("size", 3000);
1042 measurments.put("image", imageData);
1043 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(2, 2, 2), null, measurments);
1044 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2 });
1045
1046 var measurementsFilter = List.of(new FilterCondition("temperature", Operator.EQUALS, 10));
1047 var data = repository.getByKNN(
1048 containerId,
1049 new Coordinate(0, 0, 0),
1050 1,
1051 null,
1052 null,
1053 Collections.emptyMap(),
1054 measurementsFilter
1055 );
1056
1057 assertNotNull(data);
1058 assertTrue(data.isEmpty());
1059 }
1060
1061 public void getByKNN_returnsSomeData_withSkip() {
1062 var containerId = generateManagedContainerId();
1063 var metadata = new HashMap<String, Object>();
1064 metadata.put("layer", 16);
1065 metadata.put("track", 16);
1066
1067 var dataPoint1 = new SpatialDataPoint(containerId, 1l, GeometryBuilder.fromXYZ(1, 1, 1), metadata, null);
1068 var dataPoint2 = new SpatialDataPoint(containerId, 10l, GeometryBuilder.fromXYZ(2, 2, 2), metadata, null);
1069 var dataPoint3 = new SpatialDataPoint(containerId, 5l, GeometryBuilder.fromXYZ(3, 3, 3), metadata, null);
1070 var dataPoint4 = new SpatialDataPoint(containerId, 9l, GeometryBuilder.fromXYZ(4, 4, 4), metadata, null);
1071 repository.insert(containerId, new SpatialDataPoint[] { dataPoint1, dataPoint2, dataPoint3, dataPoint4 });
1072
1073 var metadataFilter = new HashMap<String, Object>();
1074 metadataFilter.put("layer", 16);
1075 var data = repository.getByKNN(
1076 containerId,
1077 new Coordinate(0, 0, 0),
1078 4,
1079 0L,
1080 20L,
1081 metadataFilter,
1082 Collections.emptyList()
1083 );
1084 assertNotNull(data);
1085 assertEquals(2, data.size());
1086 }
1087
1088 private Long generateTimestamp() {
1089 final Long timestamp = movingTimeStamp;
1090 movingTimeStamp += 10;
1091 return timestamp;
1092 }
1093 }