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