Commit 5a4cb62317051bb7aace61fd4f5da62be9a63d57
Committed by
Andrew Shvayka
1 parent
47c85fdc
Added tests for EntityMapping
Showing
1 changed file
with
567 additions
and
36 deletions
@@ -15,12 +15,14 @@ | @@ -15,12 +15,14 @@ | ||
15 | */ | 15 | */ |
16 | package org.thingsboard.server.dao.service; | 16 | package org.thingsboard.server.dao.service; |
17 | 17 | ||
18 | +import com.fasterxml.jackson.core.JsonProcessingException; | ||
19 | +import com.fasterxml.jackson.databind.JsonMappingException; | ||
20 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
18 | import com.google.common.util.concurrent.Futures; | 21 | import com.google.common.util.concurrent.Futures; |
19 | import com.google.common.util.concurrent.ListenableFuture; | 22 | import com.google.common.util.concurrent.ListenableFuture; |
20 | import org.junit.After; | 23 | import org.junit.After; |
21 | import org.junit.Assert; | 24 | import org.junit.Assert; |
22 | import org.junit.Before; | 25 | import org.junit.Before; |
23 | -import org.junit.Ignore; | ||
24 | import org.junit.Test; | 26 | import org.junit.Test; |
25 | import org.springframework.beans.factory.annotation.Autowired; | 27 | import org.springframework.beans.factory.annotation.Autowired; |
26 | import org.thingsboard.server.common.data.DataConstants; | 28 | import org.thingsboard.server.common.data.DataConstants; |
@@ -28,42 +30,23 @@ import org.thingsboard.server.common.data.Device; | @@ -28,42 +30,23 @@ import org.thingsboard.server.common.data.Device; | ||
28 | import org.thingsboard.server.common.data.EntityType; | 30 | import org.thingsboard.server.common.data.EntityType; |
29 | import org.thingsboard.server.common.data.Tenant; | 31 | import org.thingsboard.server.common.data.Tenant; |
30 | import org.thingsboard.server.common.data.asset.Asset; | 32 | import org.thingsboard.server.common.data.asset.Asset; |
31 | -import org.thingsboard.server.common.data.asset.AssetSearchQuery; | ||
32 | -import org.thingsboard.server.common.data.id.CustomerId; | ||
33 | -import org.thingsboard.server.common.data.id.DeviceId; | ||
34 | -import org.thingsboard.server.common.data.id.EntityId; | ||
35 | -import org.thingsboard.server.common.data.id.TenantId; | ||
36 | -import org.thingsboard.server.common.data.kv.AttributeKvEntry; | ||
37 | -import org.thingsboard.server.common.data.kv.BaseAttributeKvEntry; | ||
38 | -import org.thingsboard.server.common.data.kv.KvEntry; | ||
39 | -import org.thingsboard.server.common.data.kv.LongDataEntry; | 33 | +import org.thingsboard.server.common.data.id.*; |
34 | +import org.thingsboard.server.common.data.kv.*; | ||
40 | import org.thingsboard.server.common.data.page.PageData; | 35 | import org.thingsboard.server.common.data.page.PageData; |
41 | -import org.thingsboard.server.common.data.query.AssetSearchQueryFilter; | ||
42 | -import org.thingsboard.server.common.data.query.DeviceSearchQueryFilter; | ||
43 | -import org.thingsboard.server.common.data.query.DeviceTypeFilter; | ||
44 | -import org.thingsboard.server.common.data.query.EntityCountQuery; | ||
45 | -import org.thingsboard.server.common.data.query.EntityData; | ||
46 | -import org.thingsboard.server.common.data.query.EntityDataPageLink; | ||
47 | -import org.thingsboard.server.common.data.query.EntityDataQuery; | ||
48 | -import org.thingsboard.server.common.data.query.EntityDataSortOrder; | ||
49 | -import org.thingsboard.server.common.data.query.EntityKey; | ||
50 | -import org.thingsboard.server.common.data.query.EntityKeyType; | ||
51 | -import org.thingsboard.server.common.data.query.EntityListFilter; | ||
52 | -import org.thingsboard.server.common.data.query.FilterPredicateValue; | ||
53 | -import org.thingsboard.server.common.data.query.KeyFilter; | ||
54 | -import org.thingsboard.server.common.data.query.NumericFilterPredicate; | ||
55 | -import org.thingsboard.server.common.data.query.RelationsQueryFilter; | 36 | +import org.thingsboard.server.common.data.query.*; |
56 | import org.thingsboard.server.common.data.relation.EntityRelation; | 37 | import org.thingsboard.server.common.data.relation.EntityRelation; |
57 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; | 38 | import org.thingsboard.server.common.data.relation.EntitySearchDirection; |
58 | import org.thingsboard.server.common.data.relation.EntityTypeFilter; | 39 | import org.thingsboard.server.common.data.relation.EntityTypeFilter; |
59 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; | 40 | import org.thingsboard.server.common.data.relation.RelationTypeGroup; |
41 | +import org.thingsboard.server.common.data.rule.RuleChain; | ||
42 | +import org.thingsboard.server.common.data.rule.RuleChainMetaData; | ||
43 | +import org.thingsboard.server.common.data.rule.RuleNode; | ||
60 | import org.thingsboard.server.dao.attributes.AttributesService; | 44 | import org.thingsboard.server.dao.attributes.AttributesService; |
45 | +import org.thingsboard.server.dao.model.sqlts.ts.TsKvEntity; | ||
46 | +import org.thingsboard.server.dao.rule.RuleChainService; | ||
47 | +import org.thingsboard.server.dao.timeseries.TimeseriesService; | ||
61 | 48 | ||
62 | -import java.util.ArrayList; | ||
63 | -import java.util.Arrays; | ||
64 | -import java.util.Collections; | ||
65 | -import java.util.Comparator; | ||
66 | -import java.util.List; | 49 | +import java.util.*; |
67 | import java.util.concurrent.ExecutionException; | 50 | import java.util.concurrent.ExecutionException; |
68 | import java.util.stream.Collectors; | 51 | import java.util.stream.Collectors; |
69 | 52 | ||
@@ -72,6 +55,9 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -72,6 +55,9 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
72 | @Autowired | 55 | @Autowired |
73 | private AttributesService attributesService; | 56 | private AttributesService attributesService; |
74 | 57 | ||
58 | + @Autowired | ||
59 | + private TimeseriesService timeseriesService; | ||
60 | + | ||
75 | private TenantId tenantId; | 61 | private TenantId tenantId; |
76 | 62 | ||
77 | @Before | 63 | @Before |
@@ -88,6 +74,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -88,6 +74,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
88 | tenantService.deleteTenant(tenantId); | 74 | tenantService.deleteTenant(tenantId); |
89 | } | 75 | } |
90 | 76 | ||
77 | + | ||
91 | @Test | 78 | @Test |
92 | public void testCountEntitiesByQuery() throws InterruptedException { | 79 | public void testCountEntitiesByQuery() throws InterruptedException { |
93 | List<Device> devices = new ArrayList<>(); | 80 | List<Device> devices = new ArrayList<>(); |
@@ -131,6 +118,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -131,6 +118,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
131 | Assert.assertEquals(0, count); | 118 | Assert.assertEquals(0, count); |
132 | } | 119 | } |
133 | 120 | ||
121 | + | ||
134 | @Test | 122 | @Test |
135 | public void testCountHierarchicalEntitiesByQuery() throws InterruptedException { | 123 | public void testCountHierarchicalEntitiesByQuery() throws InterruptedException { |
136 | List<Asset> assets = new ArrayList<>(); | 124 | List<Asset> assets = new ArrayList<>(); |
@@ -195,6 +183,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -195,6 +183,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
195 | Assert.assertEquals(0, count); | 183 | Assert.assertEquals(0, count); |
196 | } | 184 | } |
197 | 185 | ||
186 | + | ||
198 | @Test | 187 | @Test |
199 | public void testHierarchicalFindEntityDataWithAttributesByQuery() throws ExecutionException, InterruptedException { | 188 | public void testHierarchicalFindEntityDataWithAttributesByQuery() throws ExecutionException, InterruptedException { |
200 | List<Asset> assets = new ArrayList<>(); | 189 | List<Asset> assets = new ArrayList<>(); |
@@ -266,6 +255,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -266,6 +255,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
266 | deviceService.deleteDevicesByTenantId(tenantId); | 255 | deviceService.deleteDevicesByTenantId(tenantId); |
267 | } | 256 | } |
268 | 257 | ||
258 | + | ||
269 | @Test | 259 | @Test |
270 | public void testHierarchicalFindDevicesWithAttributesByQuery() throws ExecutionException, InterruptedException { | 260 | public void testHierarchicalFindDevicesWithAttributesByQuery() throws ExecutionException, InterruptedException { |
271 | List<Asset> assets = new ArrayList<>(); | 261 | List<Asset> assets = new ArrayList<>(); |
@@ -338,6 +328,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -338,6 +328,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
338 | deviceService.deleteDevicesByTenantId(tenantId); | 328 | deviceService.deleteDevicesByTenantId(tenantId); |
339 | } | 329 | } |
340 | 330 | ||
331 | + | ||
341 | @Test | 332 | @Test |
342 | public void testHierarchicalFindAssetsWithAttributesByQuery() throws ExecutionException, InterruptedException { | 333 | public void testHierarchicalFindAssetsWithAttributesByQuery() throws ExecutionException, InterruptedException { |
343 | List<Asset> assets = new ArrayList<>(); | 334 | List<Asset> assets = new ArrayList<>(); |
@@ -456,6 +447,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -456,6 +447,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
456 | } | 447 | } |
457 | } | 448 | } |
458 | 449 | ||
450 | + | ||
459 | @Test | 451 | @Test |
460 | public void testSimpleFindEntityDataByQuery() throws InterruptedException { | 452 | public void testSimpleFindEntityDataByQuery() throws InterruptedException { |
461 | List<Device> devices = new ArrayList<>(); | 453 | List<Device> devices = new ArrayList<>(); |
@@ -526,6 +518,8 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -526,6 +518,8 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
526 | @Test | 518 | @Test |
527 | public void testFindEntityDataByQueryWithAttributes() throws ExecutionException, InterruptedException { | 519 | public void testFindEntityDataByQueryWithAttributes() throws ExecutionException, InterruptedException { |
528 | 520 | ||
521 | + List<EntityKeyType> attributesEntityTypes = new ArrayList<>(Arrays.asList(EntityKeyType.CLIENT_ATTRIBUTE, EntityKeyType.SHARED_ATTRIBUTE, EntityKeyType.SERVER_ATTRIBUTE)); | ||
522 | + | ||
529 | List<Device> devices = new ArrayList<>(); | 523 | List<Device> devices = new ArrayList<>(); |
530 | List<Long> temperatures = new ArrayList<>(); | 524 | List<Long> temperatures = new ArrayList<>(); |
531 | List<Long> highTemperatures = new ArrayList<>(); | 525 | List<Long> highTemperatures = new ArrayList<>(); |
@@ -548,6 +542,108 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -548,6 +542,108 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
548 | List<ListenableFuture<List<Void>>> attributeFutures = new ArrayList<>(); | 542 | List<ListenableFuture<List<Void>>> attributeFutures = new ArrayList<>(); |
549 | for (int i = 0; i < devices.size(); i++) { | 543 | for (int i = 0; i < devices.size(); i++) { |
550 | Device device = devices.get(i); | 544 | Device device = devices.get(i); |
545 | + for (String currentScope : DataConstants.allScopes()) { | ||
546 | + attributeFutures.add(saveLongAttribute(device.getId(), "temperature", temperatures.get(i), currentScope)); | ||
547 | + } | ||
548 | + } | ||
549 | + Futures.successfulAsList(attributeFutures).get(); | ||
550 | + | ||
551 | + DeviceTypeFilter filter = new DeviceTypeFilter(); | ||
552 | + filter.setDeviceType("default"); | ||
553 | + filter.setDeviceNameFilter(""); | ||
554 | + | ||
555 | + EntityDataSortOrder sortOrder = new EntityDataSortOrder( | ||
556 | + new EntityKey(EntityKeyType.ENTITY_FIELD, "createdTime"), EntityDataSortOrder.Direction.ASC | ||
557 | + ); | ||
558 | + EntityDataPageLink pageLink = new EntityDataPageLink(10, 0, null, sortOrder); | ||
559 | + List<EntityKey> entityFields = Collections.singletonList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name")); | ||
560 | + for (EntityKeyType currentAttributeKeyType : attributesEntityTypes) { | ||
561 | + List<EntityKey> latestValues = Collections.singletonList(new EntityKey(currentAttributeKeyType, "temperature")); | ||
562 | + EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, null); | ||
563 | + PageData<EntityData> data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
564 | + List<EntityData> loadedEntities = new ArrayList<>(data.getData()); | ||
565 | + while (data.hasNext()) { | ||
566 | + query = query.next(); | ||
567 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
568 | + loadedEntities.addAll(data.getData()); | ||
569 | + } | ||
570 | + Assert.assertEquals(67, loadedEntities.size()); | ||
571 | + List<String> loadedTemperatures = new ArrayList<>(); | ||
572 | + for (Device device : devices) { | ||
573 | + loadedTemperatures.add(loadedEntities.stream().filter(entityData -> entityData.getEntityId().equals(device.getId())).findFirst().orElse(null) | ||
574 | + .getLatest().get(currentAttributeKeyType).get("temperature").getValue()); | ||
575 | + } | ||
576 | + List<String> deviceTemperatures = temperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
577 | + Assert.assertEquals(deviceTemperatures, loadedTemperatures); | ||
578 | + | ||
579 | + pageLink = new EntityDataPageLink(10, 0, null, sortOrder); | ||
580 | + KeyFilter highTemperatureFilter = createNumericKeyFilter("temperature", currentAttributeKeyType, NumericFilterPredicate.NumericOperation.GREATER, 45); | ||
581 | + List<KeyFilter> keyFiltersHighTemperature = Collections.singletonList(highTemperatureFilter); | ||
582 | + | ||
583 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersHighTemperature); | ||
584 | + | ||
585 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
586 | + | ||
587 | + loadedEntities = new ArrayList<>(data.getData()); | ||
588 | + | ||
589 | + while (data.hasNext()) { | ||
590 | + query = query.next(); | ||
591 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
592 | + loadedEntities.addAll(data.getData()); | ||
593 | + } | ||
594 | + Assert.assertEquals(highTemperatures.size(), loadedEntities.size()); | ||
595 | + | ||
596 | + List<String> loadedHighTemperatures = loadedEntities.stream().map(entityData -> | ||
597 | + entityData.getLatest().get(currentAttributeKeyType).get("temperature").getValue()).collect(Collectors.toList()); | ||
598 | + List<String> deviceHighTemperatures = highTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
599 | + | ||
600 | + Assert.assertEquals(deviceHighTemperatures, loadedHighTemperatures); | ||
601 | + | ||
602 | + } | ||
603 | + deviceService.deleteDevicesByTenantId(tenantId); | ||
604 | + } | ||
605 | + | ||
606 | + @Test | ||
607 | + public void testBuildNumericPredicateQueryOperations() throws ExecutionException, InterruptedException{ | ||
608 | + | ||
609 | + List<Device> devices = new ArrayList<>(); | ||
610 | + List<Long> temperatures = new ArrayList<>(); | ||
611 | + List<Long> equalTemperatures = new ArrayList<>(); | ||
612 | + List<Long> notEqualTemperatures = new ArrayList<>(); | ||
613 | + List<Long> greaterTemperatures = new ArrayList<>(); | ||
614 | + List<Long> greaterOrEqualTemperatures = new ArrayList<>(); | ||
615 | + List<Long> lessTemperatures = new ArrayList<>(); | ||
616 | + List<Long> lessOrEqualTemperatures = new ArrayList<>(); | ||
617 | + | ||
618 | + for (int i = 0; i < 10; i++) { | ||
619 | + Device device = new Device(); | ||
620 | + device.setTenantId(tenantId); | ||
621 | + device.setName("Device" + i); | ||
622 | + device.setType("default"); | ||
623 | + device.setLabel("testLabel" + (int) (Math.random() * 1000)); | ||
624 | + devices.add(deviceService.saveDevice(device)); | ||
625 | + //TO make sure devices have different created time | ||
626 | + Thread.sleep(1); | ||
627 | + long temperature = (long) (Math.random() * 100); | ||
628 | + temperatures.add(temperature); | ||
629 | + if (temperature == 45) { | ||
630 | + greaterOrEqualTemperatures.add(temperature); | ||
631 | + lessOrEqualTemperatures.add(temperature); | ||
632 | + equalTemperatures.add(temperature); | ||
633 | + } else if (temperature > 45) { | ||
634 | + greaterTemperatures.add(temperature); | ||
635 | + greaterOrEqualTemperatures.add(temperature); | ||
636 | + notEqualTemperatures.add(temperature); | ||
637 | + } else { | ||
638 | + lessTemperatures.add(temperature); | ||
639 | + lessOrEqualTemperatures.add(temperature); | ||
640 | + notEqualTemperatures.add(temperature); | ||
641 | + } | ||
642 | + } | ||
643 | + | ||
644 | + List<ListenableFuture<List<Void>>> attributeFutures = new ArrayList<>(); | ||
645 | + for (int i = 0; i < devices.size(); i++) { | ||
646 | + Device device = devices.get(i); | ||
551 | attributeFutures.add(saveLongAttribute(device.getId(), "temperature", temperatures.get(i), DataConstants.CLIENT_SCOPE)); | 647 | attributeFutures.add(saveLongAttribute(device.getId(), "temperature", temperatures.get(i), DataConstants.CLIENT_SCOPE)); |
552 | } | 648 | } |
553 | Futures.successfulAsList(attributeFutures).get(); | 649 | Futures.successfulAsList(attributeFutures).get(); |
@@ -559,9 +655,155 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -559,9 +655,155 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
559 | EntityDataSortOrder sortOrder = new EntityDataSortOrder( | 655 | EntityDataSortOrder sortOrder = new EntityDataSortOrder( |
560 | new EntityKey(EntityKeyType.ENTITY_FIELD, "createdTime"), EntityDataSortOrder.Direction.ASC | 656 | new EntityKey(EntityKeyType.ENTITY_FIELD, "createdTime"), EntityDataSortOrder.Direction.ASC |
561 | ); | 657 | ); |
658 | + | ||
659 | + List<EntityKey> entityFields = Collections.singletonList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name")); | ||
660 | + List<EntityKey> latestValues = Collections.singletonList(new EntityKey(EntityKeyType.CLIENT_ATTRIBUTE, "temperature")); | ||
661 | + | ||
662 | + KeyFilter greaterTemperatureFilter = createNumericKeyFilter("temperature", EntityKeyType.CLIENT_ATTRIBUTE, NumericFilterPredicate.NumericOperation.GREATER, 45); | ||
663 | + List<KeyFilter> keyFiltersGreaterTemperature = Collections.singletonList(greaterTemperatureFilter); | ||
664 | + | ||
665 | + KeyFilter greaterOrEqualTemperatureFilter = createNumericKeyFilter("temperature", EntityKeyType.CLIENT_ATTRIBUTE, NumericFilterPredicate.NumericOperation.GREATER_OR_EQUAL, 45); | ||
666 | + List<KeyFilter> keyFiltersGreaterOrEqualTemperature = Collections.singletonList(greaterOrEqualTemperatureFilter); | ||
667 | + | ||
668 | + KeyFilter lessTemperatureFilter = createNumericKeyFilter("temperature", EntityKeyType.CLIENT_ATTRIBUTE, NumericFilterPredicate.NumericOperation.LESS, 45); | ||
669 | + List<KeyFilter> keyFiltersLessTemperature = Collections.singletonList(lessTemperatureFilter); | ||
670 | + | ||
671 | + KeyFilter lessOrEqualTemperatureFilter = createNumericKeyFilter("temperature", EntityKeyType.CLIENT_ATTRIBUTE, NumericFilterPredicate.NumericOperation.LESS_OR_EQUAL, 45); | ||
672 | + List<KeyFilter> keyFiltersLessOrEqualTemperature = Collections.singletonList(lessOrEqualTemperatureFilter); | ||
673 | + | ||
674 | + KeyFilter equalTemperatureFilter = createNumericKeyFilter("temperature", EntityKeyType.CLIENT_ATTRIBUTE, NumericFilterPredicate.NumericOperation.EQUAL, 45); | ||
675 | + List<KeyFilter> keyFiltersEqualTemperature = Collections.singletonList(equalTemperatureFilter); | ||
676 | + | ||
677 | + KeyFilter notEqualTemperatureFilter = createNumericKeyFilter("temperature", EntityKeyType.CLIENT_ATTRIBUTE, NumericFilterPredicate.NumericOperation.NOT_EQUAL, 45); | ||
678 | + List<KeyFilter> keyFiltersNotEqualTemperature = Collections.singletonList(notEqualTemperatureFilter); | ||
679 | + | ||
680 | + //Greater Operation | ||
681 | + | ||
682 | + EntityDataPageLink pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
683 | + EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersGreaterTemperature); | ||
684 | + PageData<EntityData> data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
685 | + List<EntityData> loadedEntities = getLoadedEntities(data, query); | ||
686 | + Assert.assertEquals(greaterTemperatures.size(), loadedEntities.size()); | ||
687 | + | ||
688 | + List<String> loadedTemperatures = loadedEntities.stream().map(entityData -> | ||
689 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); | ||
690 | + List<String> deviceTemperatures = greaterTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
691 | + | ||
692 | + Assert.assertEquals(deviceTemperatures, loadedTemperatures); | ||
693 | + | ||
694 | + //Greater or equal Operation | ||
695 | + | ||
696 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
697 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersGreaterOrEqualTemperature); | ||
698 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
699 | + loadedEntities = getLoadedEntities(data, query); | ||
700 | + Assert.assertEquals(greaterOrEqualTemperatures.size(), loadedEntities.size()); | ||
701 | + | ||
702 | + loadedTemperatures = loadedEntities.stream().map(entityData -> | ||
703 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); | ||
704 | + deviceTemperatures = greaterOrEqualTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
705 | + | ||
706 | + Assert.assertEquals(deviceTemperatures, loadedTemperatures); | ||
707 | + | ||
708 | + //Less Operation | ||
709 | + | ||
710 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
711 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersLessTemperature); | ||
712 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
713 | + loadedEntities = getLoadedEntities(data, query); | ||
714 | + Assert.assertEquals(lessTemperatures.size(), loadedEntities.size()); | ||
715 | + | ||
716 | + loadedTemperatures = loadedEntities.stream().map(entityData -> | ||
717 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); | ||
718 | + deviceTemperatures = lessTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
719 | + | ||
720 | + Assert.assertEquals(deviceTemperatures, loadedTemperatures); | ||
721 | + | ||
722 | + //Less or equal Operation | ||
723 | + | ||
724 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
725 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersLessOrEqualTemperature); | ||
726 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
727 | + loadedEntities = getLoadedEntities(data, query); | ||
728 | + Assert.assertEquals(lessOrEqualTemperatures.size(), loadedEntities.size()); | ||
729 | + | ||
730 | + loadedTemperatures = loadedEntities.stream().map(entityData -> | ||
731 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); | ||
732 | + deviceTemperatures = lessOrEqualTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
733 | + | ||
734 | + Assert.assertEquals(deviceTemperatures, loadedTemperatures); | ||
735 | + | ||
736 | + //Equal Operation | ||
737 | + | ||
738 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
739 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersEqualTemperature); | ||
740 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
741 | + loadedEntities = getLoadedEntities(data, query); | ||
742 | + Assert.assertEquals(equalTemperatures.size(), loadedEntities.size()); | ||
743 | + | ||
744 | + loadedTemperatures = loadedEntities.stream().map(entityData -> | ||
745 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); | ||
746 | + deviceTemperatures = equalTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
747 | + | ||
748 | + Assert.assertEquals(deviceTemperatures, loadedTemperatures); | ||
749 | + | ||
750 | + //Not equal Operation | ||
751 | + | ||
752 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
753 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersNotEqualTemperature); | ||
754 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
755 | + loadedEntities = getLoadedEntities(data, query); | ||
756 | + Assert.assertEquals(notEqualTemperatures.size(), loadedEntities.size()); | ||
757 | + | ||
758 | + loadedTemperatures = loadedEntities.stream().map(entityData -> | ||
759 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); | ||
760 | + deviceTemperatures = notEqualTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | ||
761 | + | ||
762 | + Assert.assertEquals(deviceTemperatures, loadedTemperatures); | ||
763 | + | ||
764 | + | ||
765 | + deviceService.deleteDevicesByTenantId(tenantId); | ||
766 | + } | ||
767 | + | ||
768 | + @Test | ||
769 | + public void testFindEntityDataByQueryWithTimeseries() throws ExecutionException, InterruptedException { | ||
770 | + | ||
771 | + List<Device> devices = new ArrayList<>(); | ||
772 | + List<Double> temperatures = new ArrayList<>(); | ||
773 | + List<Double> highTemperatures = new ArrayList<>(); | ||
774 | + for (int i = 0; i < 67; i++) { | ||
775 | + Device device = new Device(); | ||
776 | + device.setTenantId(tenantId); | ||
777 | + device.setName("Device" + i); | ||
778 | + device.setType("default"); | ||
779 | + device.setLabel("testLabel" + (int) (Math.random() * 1000)); | ||
780 | + devices.add(deviceService.saveDevice(device)); | ||
781 | + //TO make sure devices have different created time | ||
782 | + Thread.sleep(1); | ||
783 | + double temperature = (double) (Math.random() * 100.0); | ||
784 | + temperatures.add(temperature); | ||
785 | + if (temperature > 45.0) { | ||
786 | + highTemperatures.add(temperature); | ||
787 | + } | ||
788 | + } | ||
789 | + | ||
790 | + List<ListenableFuture<List<Void>>> timeseriesFutures = new ArrayList<>(); | ||
791 | + for (int i = 0; i < devices.size(); i++) { | ||
792 | + Device device = devices.get(i); | ||
793 | + timeseriesFutures.add(saveLongTimeseries(device.getId(), "temperature", temperatures.get(i))); | ||
794 | + } | ||
795 | + Futures.successfulAsList(timeseriesFutures).get(); | ||
796 | + | ||
797 | + DeviceTypeFilter filter = new DeviceTypeFilter(); | ||
798 | + filter.setDeviceType("default"); | ||
799 | + filter.setDeviceNameFilter(""); | ||
800 | + | ||
801 | + EntityDataSortOrder sortOrder = new EntityDataSortOrder( | ||
802 | + new EntityKey(EntityKeyType.ENTITY_FIELD, "createdTime"), EntityDataSortOrder.Direction.ASC | ||
803 | + ); | ||
562 | EntityDataPageLink pageLink = new EntityDataPageLink(10, 0, null, sortOrder); | 804 | EntityDataPageLink pageLink = new EntityDataPageLink(10, 0, null, sortOrder); |
563 | List<EntityKey> entityFields = Collections.singletonList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name")); | 805 | List<EntityKey> entityFields = Collections.singletonList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name")); |
564 | - List<EntityKey> latestValues = Collections.singletonList(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); | 806 | + List<EntityKey> latestValues = Collections.singletonList(new EntityKey(EntityKeyType.TIME_SERIES, "temperature")); |
565 | 807 | ||
566 | EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, null); | 808 | EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, null); |
567 | PageData<EntityData> data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | 809 | PageData<EntityData> data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); |
@@ -576,14 +818,14 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -576,14 +818,14 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
576 | List<String> loadedTemperatures = new ArrayList<>(); | 818 | List<String> loadedTemperatures = new ArrayList<>(); |
577 | for (Device device : devices) { | 819 | for (Device device : devices) { |
578 | loadedTemperatures.add(loadedEntities.stream().filter(entityData -> entityData.getEntityId().equals(device.getId())).findFirst().orElse(null) | 820 | loadedTemperatures.add(loadedEntities.stream().filter(entityData -> entityData.getEntityId().equals(device.getId())).findFirst().orElse(null) |
579 | - .getLatest().get(EntityKeyType.ATTRIBUTE).get("temperature").getValue()); | 821 | + .getLatest().get(EntityKeyType.TIME_SERIES).get("temperature").getValue()); |
580 | } | 822 | } |
581 | - List<String> deviceTemperatures = temperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | 823 | + List<String> deviceTemperatures = temperatures.stream().map(aDouble -> Double.toString(aDouble)).collect(Collectors.toList()); |
582 | Assert.assertEquals(deviceTemperatures, loadedTemperatures); | 824 | Assert.assertEquals(deviceTemperatures, loadedTemperatures); |
583 | 825 | ||
584 | pageLink = new EntityDataPageLink(10, 0, null, sortOrder); | 826 | pageLink = new EntityDataPageLink(10, 0, null, sortOrder); |
585 | KeyFilter highTemperatureFilter = new KeyFilter(); | 827 | KeyFilter highTemperatureFilter = new KeyFilter(); |
586 | - highTemperatureFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); | 828 | + highTemperatureFilter.setKey(new EntityKey(EntityKeyType.TIME_SERIES, "temperature")); |
587 | NumericFilterPredicate predicate = new NumericFilterPredicate(); | 829 | NumericFilterPredicate predicate = new NumericFilterPredicate(); |
588 | predicate.setValue(FilterPredicateValue.fromDouble(45)); | 830 | predicate.setValue(FilterPredicateValue.fromDouble(45)); |
589 | predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); | 831 | predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); |
@@ -603,17 +845,306 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | @@ -603,17 +845,306 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { | ||
603 | Assert.assertEquals(highTemperatures.size(), loadedEntities.size()); | 845 | Assert.assertEquals(highTemperatures.size(), loadedEntities.size()); |
604 | 846 | ||
605 | List<String> loadedHighTemperatures = loadedEntities.stream().map(entityData -> | 847 | List<String> loadedHighTemperatures = loadedEntities.stream().map(entityData -> |
606 | - entityData.getLatest().get(EntityKeyType.ATTRIBUTE).get("temperature").getValue()).collect(Collectors.toList()); | ||
607 | - List<String> deviceHighTemperatures = highTemperatures.stream().map(aLong -> Long.toString(aLong)).collect(Collectors.toList()); | 848 | + entityData.getLatest().get(EntityKeyType.TIME_SERIES).get("temperature").getValue()).collect(Collectors.toList()); |
849 | + List<String> deviceHighTemperatures = highTemperatures.stream().map(aDouble -> Double.toString(aDouble)).collect(Collectors.toList()); | ||
608 | 850 | ||
609 | Assert.assertEquals(deviceHighTemperatures, loadedHighTemperatures); | 851 | Assert.assertEquals(deviceHighTemperatures, loadedHighTemperatures); |
610 | 852 | ||
611 | deviceService.deleteDevicesByTenantId(tenantId); | 853 | deviceService.deleteDevicesByTenantId(tenantId); |
612 | } | 854 | } |
613 | 855 | ||
856 | + @Test | ||
857 | + public void testBuildStringPredicateQueryOperations() throws ExecutionException, InterruptedException{ | ||
858 | + | ||
859 | + List<Device> devices = new ArrayList<>(); | ||
860 | + List<String> attributeStrings = new ArrayList<>(); | ||
861 | + List<String> equalStrings = new ArrayList<>(); | ||
862 | + List<String> notEqualStrings = new ArrayList<>(); | ||
863 | + List<String> startsWithStrings = new ArrayList<>(); | ||
864 | + List<String> endsWithStrings = new ArrayList<>(); | ||
865 | + List<String> containsStrings = new ArrayList<>(); | ||
866 | + List<String> notContainsStrings = new ArrayList<>(); | ||
867 | + | ||
868 | + for (int i = 0; i < 10; i++) { | ||
869 | + Device device = new Device(); | ||
870 | + device.setTenantId(tenantId); | ||
871 | + device.setName("Device" + i); | ||
872 | + device.setType("default"); | ||
873 | + device.setLabel("testLabel" + (int) (Math.random() * 1000)); | ||
874 | + devices.add(deviceService.saveDevice(device)); | ||
875 | + //TO make sure devices have different created time | ||
876 | + Thread.sleep(1); | ||
877 | + List<StringFilterPredicate.StringOperation> operationValues= Arrays.asList(StringFilterPredicate.StringOperation.values()); | ||
878 | + StringFilterPredicate.StringOperation operation = operationValues.get(new Random().nextInt(operationValues.size())); | ||
879 | + String operationName = operation.name(); | ||
880 | + attributeStrings.add(operationName); | ||
881 | + switch(operation){ | ||
882 | + case EQUAL: | ||
883 | + equalStrings.add(operationName); | ||
884 | + notContainsStrings.add(operationName); | ||
885 | + notEqualStrings.add(operationName); | ||
886 | + break; | ||
887 | + case NOT_EQUAL: | ||
888 | + notContainsStrings.add(operationName); | ||
889 | + break; | ||
890 | + case STARTS_WITH: | ||
891 | + notEqualStrings.add(operationName); | ||
892 | + startsWithStrings.add(operationName); | ||
893 | + endsWithStrings.add(operationName); | ||
894 | + notContainsStrings.add(operationName); | ||
895 | + break; | ||
896 | + case ENDS_WITH: | ||
897 | + notEqualStrings.add(operationName); | ||
898 | + endsWithStrings.add(operationName); | ||
899 | + notContainsStrings.add(operationName); | ||
900 | + break; | ||
901 | + case CONTAINS: | ||
902 | + notEqualStrings.add(operationName); | ||
903 | + notContainsStrings.add(operationName); | ||
904 | + containsStrings.add(operationName); | ||
905 | + break; | ||
906 | + case NOT_CONTAINS: | ||
907 | + notEqualStrings.add(operationName); | ||
908 | + containsStrings.add(operationName); | ||
909 | + break; | ||
910 | + } | ||
911 | + } | ||
912 | + | ||
913 | + List<ListenableFuture<List<Void>>> attributeFutures = new ArrayList<>(); | ||
914 | + for (int i = 0; i < devices.size(); i++) { | ||
915 | + Device device = devices.get(i); | ||
916 | + attributeFutures.add(saveStringAttribute(device.getId(), "attributeString", attributeStrings.get(i), DataConstants.CLIENT_SCOPE)); | ||
917 | + } | ||
918 | + Futures.successfulAsList(attributeFutures).get(); | ||
919 | + | ||
920 | + DeviceTypeFilter filter = new DeviceTypeFilter(); | ||
921 | + filter.setDeviceType("default"); | ||
922 | + filter.setDeviceNameFilter(""); | ||
923 | + | ||
924 | + EntityDataSortOrder sortOrder = new EntityDataSortOrder( | ||
925 | + new EntityKey(EntityKeyType.ENTITY_FIELD, "createdTime"), EntityDataSortOrder.Direction.DESC | ||
926 | + ); | ||
927 | + | ||
928 | + List<EntityKey> entityFields = Arrays.asList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name"), new EntityKey(EntityKeyType.ENTITY_FIELD, "deviceType")); | ||
929 | + List<EntityKey> latestValues = Collections.singletonList(new EntityKey(EntityKeyType.CLIENT_ATTRIBUTE, "attributeString")); | ||
930 | + | ||
931 | + List<KeyFilter> keyFiltersEqualString = createStringKeyFilters("attributeString", EntityKeyType.CLIENT_ATTRIBUTE, StringFilterPredicate.StringOperation.EQUAL, "equal"); | ||
932 | + | ||
933 | + List<KeyFilter> keyFiltersNotEqualString = createStringKeyFilters("attributeString", EntityKeyType.CLIENT_ATTRIBUTE, StringFilterPredicate.StringOperation.NOT_EQUAL, "NOT_EQUAL"); | ||
934 | + | ||
935 | + List<KeyFilter> keyFiltersStartsWithString = createStringKeyFilters("attributeString", EntityKeyType.CLIENT_ATTRIBUTE, StringFilterPredicate.StringOperation.STARTS_WITH, "starts_"); | ||
936 | + | ||
937 | + List<KeyFilter> keyFiltersEndsWithString = createStringKeyFilters("attributeString", EntityKeyType.CLIENT_ATTRIBUTE, StringFilterPredicate.StringOperation.ENDS_WITH, "_WITH"); | ||
938 | + | ||
939 | + List<KeyFilter> keyFiltersContainsString = createStringKeyFilters("attributeString", EntityKeyType.CLIENT_ATTRIBUTE, StringFilterPredicate.StringOperation.CONTAINS, "contains"); | ||
940 | + | ||
941 | + List<KeyFilter> keyFiltersNotContainsString = createStringKeyFilters("attributeString", EntityKeyType.CLIENT_ATTRIBUTE, StringFilterPredicate.StringOperation.NOT_CONTAINS, "NOT_CONTAINS"); | ||
942 | + | ||
943 | + List<KeyFilter> deviceTypeFilters = createStringKeyFilters("entityType", EntityKeyType.ENTITY_FIELD, StringFilterPredicate.StringOperation.EQUAL, "EQUAL"); | ||
944 | + | ||
945 | + // Equal Operation | ||
946 | + | ||
947 | + EntityDataPageLink pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
948 | + EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersEqualString); | ||
949 | + PageData<EntityData> data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
950 | + List<EntityData> loadedEntities = getLoadedEntities(data, query); | ||
951 | + Assert.assertEquals(equalStrings.size(), loadedEntities.size()); | ||
952 | + | ||
953 | + List<String> loadedStrings = loadedEntities.stream().map(entityData -> | ||
954 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("attributeString").getValue()).collect(Collectors.toList()); | ||
955 | + | ||
956 | + Assert.assertTrue(listEqualWithoutOrder(equalStrings, loadedStrings)); | ||
957 | + | ||
958 | + // Not equal Operation | ||
959 | + | ||
960 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
961 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersNotEqualString); | ||
962 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
963 | + loadedEntities = getLoadedEntities(data, query); | ||
964 | + Assert.assertEquals(notEqualStrings.size(), loadedEntities.size()); | ||
965 | + | ||
966 | + loadedStrings = loadedEntities.stream().map(entityData -> | ||
967 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("attributeString").getValue()).collect(Collectors.toList()); | ||
968 | + | ||
969 | + Assert.assertTrue(listEqualWithoutOrder(notEqualStrings, loadedStrings)); | ||
970 | + | ||
971 | + // Starts with Operation | ||
972 | + | ||
973 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
974 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersStartsWithString); | ||
975 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
976 | + loadedEntities = getLoadedEntities(data, query); | ||
977 | + Assert.assertEquals(startsWithStrings.size(), loadedEntities.size()); | ||
978 | + | ||
979 | + loadedStrings = loadedEntities.stream().map(entityData -> | ||
980 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("attributeString").getValue()).collect(Collectors.toList()); | ||
981 | + | ||
982 | + Assert.assertTrue(listEqualWithoutOrder(startsWithStrings, loadedStrings)); | ||
983 | + | ||
984 | + // Ends with Operation | ||
985 | + | ||
986 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
987 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersEndsWithString); | ||
988 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
989 | + loadedEntities = getLoadedEntities(data, query); | ||
990 | + Assert.assertEquals(endsWithStrings.size(), loadedEntities.size()); | ||
991 | + | ||
992 | + loadedStrings = loadedEntities.stream().map(entityData -> | ||
993 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("attributeString").getValue()).collect(Collectors.toList()); | ||
994 | + | ||
995 | + Assert.assertTrue(listEqualWithoutOrder(endsWithStrings, loadedStrings)); | ||
996 | + | ||
997 | + // Contains Operation | ||
998 | + | ||
999 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
1000 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersContainsString); | ||
1001 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
1002 | + loadedEntities = getLoadedEntities(data, query); | ||
1003 | + Assert.assertEquals(containsStrings.size(), loadedEntities.size()); | ||
1004 | + | ||
1005 | + loadedStrings = loadedEntities.stream().map(entityData -> | ||
1006 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("attributeString").getValue()).collect(Collectors.toList()); | ||
1007 | + | ||
1008 | + Assert.assertTrue(listEqualWithoutOrder(containsStrings, loadedStrings)); | ||
1009 | + | ||
1010 | + // Not contains Operation | ||
1011 | + | ||
1012 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
1013 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, keyFiltersNotContainsString); | ||
1014 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
1015 | + loadedEntities = getLoadedEntities(data, query); | ||
1016 | + Assert.assertEquals(notContainsStrings.size(), loadedEntities.size()); | ||
1017 | + | ||
1018 | + loadedStrings = loadedEntities.stream().map(entityData -> | ||
1019 | + entityData.getLatest().get(EntityKeyType.CLIENT_ATTRIBUTE).get("attributeString").getValue()).collect(Collectors.toList()); | ||
1020 | + | ||
1021 | + Assert.assertTrue(listEqualWithoutOrder(notContainsStrings, loadedStrings)); | ||
1022 | + | ||
1023 | + // Device type filters Operation | ||
1024 | + | ||
1025 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
1026 | + query = new EntityDataQuery(filter, pageLink, entityFields, latestValues, deviceTypeFilters); | ||
1027 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
1028 | + loadedEntities = getLoadedEntities(data, query); | ||
1029 | + Assert.assertEquals(devices.size(), loadedEntities.size()); | ||
1030 | + | ||
1031 | + deviceService.deleteDevicesByTenantId(tenantId); | ||
1032 | + } | ||
1033 | + | ||
1034 | + @Test | ||
1035 | + public void testBuildSimplePredicateQueryOperations() throws JsonMappingException, JsonProcessingException, ExecutionException, InterruptedException{ | ||
1036 | + | ||
1037 | + List<Device> devices = new ArrayList<>(); | ||
1038 | + | ||
1039 | + for (int i = 0; i < 10; i++) { | ||
1040 | + Device device = new Device(); | ||
1041 | + device.setTenantId(tenantId); | ||
1042 | + device.setName("Device" + i); | ||
1043 | + device.setType("default"); | ||
1044 | + device.setLabel("testLabel" + (int) (Math.random() * 1000)); | ||
1045 | + devices.add(deviceService.saveDevice(device)); | ||
1046 | + //TO make sure devices have different created time | ||
1047 | + Thread.sleep(1); | ||
1048 | + } | ||
1049 | + | ||
1050 | + DeviceTypeFilter filter = new DeviceTypeFilter(); | ||
1051 | + filter.setDeviceType("default"); | ||
1052 | + filter.setDeviceNameFilter(""); | ||
1053 | + | ||
1054 | + EntityDataSortOrder sortOrder = new EntityDataSortOrder(new EntityKey(EntityKeyType.ENTITY_FIELD, "name"), EntityDataSortOrder.Direction.DESC); | ||
1055 | + | ||
1056 | + List<KeyFilter> deviceTypeFilters = createStringKeyFilters("entityType", EntityKeyType.ENTITY_FIELD, StringFilterPredicate.StringOperation.EQUAL, "EQUAL"); | ||
1057 | + | ||
1058 | + KeyFilter createdTimeFilter = createNumericKeyFilter("createdTime", EntityKeyType.ENTITY_FIELD, NumericFilterPredicate.NumericOperation.GREATER, 1L); | ||
1059 | + List<KeyFilter> createdTimeFilters = Collections.singletonList(createdTimeFilter); | ||
1060 | + | ||
1061 | + List<KeyFilter> nameFilters = createStringKeyFilters("name", EntityKeyType.ENTITY_FIELD, StringFilterPredicate.StringOperation.CONTAINS, "Device"); | ||
1062 | + | ||
1063 | + List<EntityKey> entityFields = Arrays.asList(new EntityKey(EntityKeyType.ENTITY_FIELD, "name"), | ||
1064 | + new EntityKey(EntityKeyType.ENTITY_FIELD, "type")); | ||
1065 | + | ||
1066 | + // Device type filters | ||
1067 | + | ||
1068 | + EntityDataPageLink pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
1069 | + EntityDataQuery query = new EntityDataQuery(filter, pageLink, entityFields, null, deviceTypeFilters); | ||
1070 | + PageData data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
1071 | + List<EntityData> loadedEntities = getLoadedEntities(data, query); | ||
1072 | + Assert.assertEquals(devices.size(), loadedEntities.size()); | ||
1073 | + | ||
1074 | + // Device create time filters | ||
1075 | + | ||
1076 | + pageLink = new EntityDataPageLink(100, 0, null, sortOrder); | ||
1077 | + query = new EntityDataQuery(filter, pageLink, entityFields, null, createdTimeFilters); | ||
1078 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
1079 | + loadedEntities = getLoadedEntities(data, query); | ||
1080 | + Assert.assertEquals(devices.size(), loadedEntities.size()); | ||
1081 | + | ||
1082 | + // Device name filters | ||
1083 | + | ||
1084 | + pageLink = new EntityDataPageLink(100, 0, null, null); | ||
1085 | + query = new EntityDataQuery(filter, pageLink, entityFields, null, nameFilters); | ||
1086 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
1087 | + loadedEntities = getLoadedEntities(data, query); | ||
1088 | + Assert.assertEquals(devices.size(), loadedEntities.size()); | ||
1089 | + | ||
1090 | + deviceService.deleteDevicesByTenantId(tenantId); | ||
1091 | + } | ||
1092 | + | ||
1093 | + private Boolean listEqualWithoutOrder(List<String> A, List<String> B) { | ||
1094 | + return A.containsAll(B) && B.containsAll(A); | ||
1095 | + } | ||
1096 | + | ||
1097 | + private List<EntityData> getLoadedEntities(PageData data, EntityDataQuery query) { | ||
1098 | + List<EntityData> loadedEntities = new ArrayList<>(data.getData()); | ||
1099 | + | ||
1100 | + while (data.hasNext()) { | ||
1101 | + query = query.next(); | ||
1102 | + data = entityService.findEntityDataByQuery(tenantId, new CustomerId(CustomerId.NULL_UUID), query); | ||
1103 | + loadedEntities.addAll(data.getData()); | ||
1104 | + } | ||
1105 | + return loadedEntities; | ||
1106 | + } | ||
1107 | + | ||
1108 | + private List<KeyFilter> createStringKeyFilters(String key, EntityKeyType keyType, StringFilterPredicate.StringOperation operation, String value){ | ||
1109 | + KeyFilter filter = new KeyFilter(); | ||
1110 | + filter.setKey(new EntityKey(keyType, key)); | ||
1111 | + StringFilterPredicate predicate = new StringFilterPredicate(); | ||
1112 | + predicate.setValue(FilterPredicateValue.fromString(value)); | ||
1113 | + predicate.setOperation(operation); | ||
1114 | + predicate.setIgnoreCase(true); | ||
1115 | + filter.setPredicate(predicate); | ||
1116 | + return Collections.singletonList(filter); | ||
1117 | + } | ||
1118 | + | ||
1119 | + private KeyFilter createNumericKeyFilter(String key, EntityKeyType keyType, NumericFilterPredicate.NumericOperation operation, double value){ | ||
1120 | + KeyFilter filter = new KeyFilter(); | ||
1121 | + filter.setKey(new EntityKey(keyType, key)); | ||
1122 | + NumericFilterPredicate predicate = new NumericFilterPredicate(); | ||
1123 | + predicate.setValue(FilterPredicateValue.fromDouble(value)); | ||
1124 | + predicate.setOperation(operation); | ||
1125 | + filter.setPredicate(predicate); | ||
1126 | + | ||
1127 | + return filter; | ||
1128 | + } | ||
1129 | + | ||
614 | private ListenableFuture<List<Void>> saveLongAttribute(EntityId entityId, String key, long value, String scope) { | 1130 | private ListenableFuture<List<Void>> saveLongAttribute(EntityId entityId, String key, long value, String scope) { |
615 | KvEntry attrValue = new LongDataEntry(key, value); | 1131 | KvEntry attrValue = new LongDataEntry(key, value); |
616 | AttributeKvEntry attr = new BaseAttributeKvEntry(attrValue, 42L); | 1132 | AttributeKvEntry attr = new BaseAttributeKvEntry(attrValue, 42L); |
617 | return attributesService.save(SYSTEM_TENANT_ID, entityId, scope, Collections.singletonList(attr)); | 1133 | return attributesService.save(SYSTEM_TENANT_ID, entityId, scope, Collections.singletonList(attr)); |
618 | } | 1134 | } |
1135 | + | ||
1136 | + private ListenableFuture<List<Void>> saveStringAttribute(EntityId entityId, String key, String value, String scope) { | ||
1137 | + KvEntry attrValue = new StringDataEntry(key, value); | ||
1138 | + AttributeKvEntry attr = new BaseAttributeKvEntry(attrValue, 42L); | ||
1139 | + return attributesService.save(SYSTEM_TENANT_ID, entityId, scope, Collections.singletonList(attr)); | ||
1140 | + } | ||
1141 | + | ||
1142 | + private ListenableFuture<List<Void>> saveLongTimeseries(EntityId entityId, String key, Double value) { | ||
1143 | + TsKvEntity tsKv = new TsKvEntity(); | ||
1144 | + tsKv.setStrKey(key); | ||
1145 | + tsKv.setDoubleValue(value); | ||
1146 | + KvEntry telemetryValue = new DoubleDataEntry(key, value); | ||
1147 | + BasicTsKvEntry timeseries = new BasicTsKvEntry(42L, telemetryValue); | ||
1148 | + return timeseriesService.save(SYSTEM_TENANT_ID, entityId, timeseries); | ||
1149 | + } | ||
619 | } | 1150 | } |