From 3c5b76b25d580b2be8f3741f40ed21db34a3fad8 Mon Sep 17 00:00:00 2001 From: mp-loki Date: Mon, 29 May 2017 23:47:45 -0400 Subject: [PATCH] Added method implementations to missing JPA Asset and Alalrm DAO methods --- .../common/data/asset/TenantAssetType.java | 7 ++ .../server/dao/sql/JpaAbstractDao.java | 1 - .../server/dao/sql/alarm/AlarmRepository.java | 2 +- .../server/dao/sql/alarm/JpaAlarmDao.java | 34 ++++++-- .../server/dao/sql/asset/AssetRepository.java | 16 ++++ .../server/dao/sql/asset/JpaAssetDao.java | 11 ++- .../dao/sql/relation/JpaRelationDao.java | 84 +++++++++++++++++++ .../server/dao/sql/alarm/JpaAlarmDaoTest.java | 5 ++ .../server/dao/sql/asset/JpaAssetDaoTest.java | 66 +++++++++++++-- 9 files changed, 205 insertions(+), 21 deletions(-) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/asset/TenantAssetType.java b/common/data/src/main/java/org/thingsboard/server/common/data/asset/TenantAssetType.java index bd23f2aa5a..8e0eb0e69e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/TenantAssetType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/asset/TenantAssetType.java @@ -17,6 +17,8 @@ package org.thingsboard.server.common.data.asset; import org.thingsboard.server.common.data.id.TenantId; +import java.util.UUID; + public class TenantAssetType { private static final long serialVersionUID = 8057290243855622101L; @@ -33,6 +35,11 @@ public class TenantAssetType { this.tenantId = tenantId; } + public TenantAssetType(String type, UUID tenantId) { + this.type = type; + this.tenantId = new TenantId(tenantId); + } + public String getType() { return type; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java index 7073b491ac..a2b2bc9150 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java @@ -76,7 +76,6 @@ public abstract class JpaAbstractDao, D> implements Dao< @Override public ListenableFuture findByIdAsync(UUID key) { log.debug("Get entity by key async {}", key); - // Should ListeningExecutorService be a field? ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)); ListenableFuture listenableFuture = service.submit(() -> DaoUtil.getData(getCrudRepository().findOne(key))); return listenableFuture; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java index f14a08f7eb..e46c144692 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/AlarmRepository.java @@ -27,7 +27,7 @@ import java.util.UUID; * Created by Valerii Sosliuk on 5/21/2017. */ @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) -public interface AlarmRepository extends CrudRepository { +public interface AlarmRepository extends CrudRepository { @Query(nativeQuery = true, value = "SELECT * FROM ALARM WHERE TENANT_ID = ?1 AND ORIGINATOR_ID = ?2 " + "AND ?3 = ?3 AND TYPE = ?4 ORDER BY ID DESC LIMIT 1") diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java index 86ad73692e..cd0df63c32 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDao.java @@ -15,23 +15,28 @@ */ package org.thingsboard.server.dao.sql.alarm; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.*; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.AlarmQuery; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.alarm.AlarmDao; +import org.thingsboard.server.dao.alarm.BaseAlarmService; import org.thingsboard.server.dao.model.sql.AlarmEntity; +import org.thingsboard.server.dao.relation.RelationDao; import org.thingsboard.server.dao.sql.JpaAbstractDao; +import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.Executors; @@ -41,6 +46,7 @@ import static org.springframework.transaction.annotation.Propagation.REQUIRES_NE /** * Created by Valerii Sosliuk on 5/19/2017. */ +@Slf4j @Component @ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) public class JpaAlarmDao extends JpaAbstractDao implements AlarmDao { @@ -48,6 +54,9 @@ public class JpaAlarmDao extends JpaAbstractDao implements A @Autowired private AlarmRepository alarmRepository; + @Autowired + private RelationDao relationDao; + @Override protected Class getEntityClass() { return AlarmEntity.class; @@ -62,21 +71,28 @@ public class JpaAlarmDao extends JpaAbstractDao implements A @Transactional(propagation = REQUIRES_NEW) public ListenableFuture findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type) { ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)); - ListenableFuture listenableFuture = service.submit(() -> DaoUtil.getData( + return service.submit(() -> DaoUtil.getData( alarmRepository.findLatestByOriginatorAndType(tenantId.getId(), originator.getId(), originator.getEntityType().ordinal(), type))); - return listenableFuture; } @Override public ListenableFuture findAlarmByIdAsync(UUID key) { - //TODO: Implement - return null; + return findByIdAsync(key); } @Override public ListenableFuture> findAlarms(AlarmQuery query) { - //TODO: Implement - return null; + log.trace("Try to find alarms by entity [{}], status [{}] and pageLink [{}]", query.getAffectedEntityId(), query.getStatus(), query.getPageLink()); + EntityId affectedEntity = query.getAffectedEntityId(); + String relationType = query.getStatus() == null ? BaseAlarmService.ALARM_RELATION : BaseAlarmService.ALARM_RELATION_PREFIX + query.getStatus().name(); + ListenableFuture> relations = relationDao.findRelations(affectedEntity, relationType, RelationTypeGroup.ALARM, EntityType.ALARM, query.getPageLink()); + return Futures.transform(relations, (AsyncFunction, List>) input -> { + List> alarmFutures = new ArrayList<>(input.size()); + for (EntityRelation relation : input) { + alarmFutures.add(findAlarmByIdAsync(relation.getTo().getId())); + } + return Futures.successfulAsList(alarmFutures); + }); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java index cf38c02988..b6c9891540 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java @@ -19,6 +19,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.asset.TenantAssetType; import org.thingsboard.server.dao.model.sql.AssetEntity; import java.util.List; @@ -58,4 +59,19 @@ public interface AssetRepository extends CrudRepository { List findByTenantIdAndCustomerIdAndIdIn(UUID tenantId, UUID customerId, List assetIds); AssetEntity findByTenantIdAndName(UUID tenantId, String name); + + @Query(nativeQuery = true, value = "SELECT * FROM ASSET WHERE TENANT_ID = ?2 " + + "AND CUSTOMER_ID = ?3 AND TYPE = ?4 " + + "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?5, '%')) " + + "ORDER BY ID LIMIT ?1") + List findByTenantIdAndCustomerIdAndTypeFirstPage(int limit, UUID tenantId, UUID customerId, String type, String textSearch); + + @Query(nativeQuery = true, value = "SELECT * FROM ASSET WHERE TENANT_ID = ?2 " + + "AND CUSTOMER_ID = ?3 AND TYPE = ?4 " + + "AND LOWER(SEARCH_TEXT) LIKE LOWER(CONCAT(?5, '%')) " + + "AND ID > ?6 ORDER BY ID LIMIT ?1") + List findByTenantIdAndCustomerIdAndTypeNextPage(int limit, UUID tenantId, UUID customerId, String type, String textSearch, UUID idOffset); + + @Query(value = "SELECT NEW org.thingsboard.server.common.data.asset.TenantAssetType(a.type, a.tenantId) FROM AssetEntity a GROUP BY a.tenantId, a.type") + List findTenantAssetTypes(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java index bc52aa088f..49f8d44e05 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java @@ -104,11 +104,18 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im @Override public List findAssetsByTenantIdAndCustomerIdAndType(UUID tenantId, UUID customerId, String type, TextPageLink pageLink) { - return null; + if (pageLink.getIdOffset() == null) { + return DaoUtil.convertDataList(assetRepository.findByTenantIdAndCustomerIdAndTypeFirstPage(pageLink.getLimit(), tenantId, + customerId, type, pageLink.getTextSearch())); + } else { + return DaoUtil.convertDataList(assetRepository.findByTenantIdAndCustomerIdAndTypeNextPage(pageLink.getLimit(), tenantId, + customerId, type, pageLink.getTextSearch(), pageLink.getIdOffset())); + } } @Override public ListenableFuture> findTenantAssetTypesAsync() { - return null; + ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10)); + return service.submit(() -> assetRepository.findTenantAssetTypes()); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java new file mode 100644 index 0000000000..beaa9c64ac --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/relation/JpaRelationDao.java @@ -0,0 +1,84 @@ +package org.thingsboard.server.dao.sql.relation; + +import com.google.common.util.concurrent.ListenableFuture; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.page.TimePageLink; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.dao.relation.RelationDao; + +import java.util.List; + +/** + * Created by Valerii Sosliuk on 5/29/2017. + */ +@Slf4j +@Component +@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false) +public class JpaRelationDao implements RelationDao { + + + @Override + public ListenableFuture> findAllByFrom(EntityId from, RelationTypeGroup typeGroup) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture> findAllByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture> findAllByTo(EntityId to, RelationTypeGroup typeGroup) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture> findAllByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture saveRelation(EntityRelation relation) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture deleteRelation(EntityRelation relation) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture deleteRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture deleteOutboundRelations(EntityId entity) { + // TODO: Implement + return null; + } + + @Override + public ListenableFuture> findRelations(EntityId from, String relationType, RelationTypeGroup typeGroup, EntityType toType, TimePageLink pageLink) { + // TODO: Implement + return null; + } +} diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDaoTest.java index 94b6f51c33..b26db0bb97 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/alarm/JpaAlarmDaoTest.java @@ -71,6 +71,11 @@ public class JpaAlarmDaoTest extends AbstractJpaDaoTest { assertEquals(alarm2Id, alarm.getId().getId()); } + @Test + public void testFindAlarmByIdAsync() { + // TODO: implement + } + private void saveAlarm(UUID id, UUID tenantId, UUID deviceId, String type) { Alarm alarm = new Alarm(); alarm.setId(new AlarmId(id)); diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/asset/JpaAssetDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/asset/JpaAssetDaoTest.java index ebee17e4bc..4be102e089 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/asset/JpaAssetDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/asset/JpaAssetDaoTest.java @@ -20,6 +20,7 @@ import com.google.common.util.concurrent.ListenableFuture; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.asset.Asset; +import org.thingsboard.server.common.data.asset.TenantAssetType; import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -32,6 +33,7 @@ import java.util.List; import java.util.Optional; import java.util.UUID; import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; import static junit.framework.TestCase.assertFalse; import static org.junit.Assert.assertEquals; @@ -56,7 +58,7 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { UUID assetId = UUIDs.timeBased(); UUID tenantId = i % 2 == 0 ? tenantId1 : tenantId2; UUID customerId = i % 2 == 0 ? customerId1 : customerId2; - saveAsset(assetId, tenantId, customerId, "ASSET_" + i); + saveAsset(assetId, tenantId, customerId, "ASSET_" + i, "TYPE_1"); } assertEquals(60, assetDao.find().size()); @@ -83,7 +85,7 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { UUID assetId = UUIDs.timeBased(); UUID tenantId = i % 2 == 0 ? tenantId1 : tenantId2; UUID customerId = i % 2 == 0 ? customerId1 : customerId2; - saveAsset(assetId, tenantId, customerId, "ASSET_" + i); + saveAsset(assetId, tenantId, customerId, "ASSET_" + i, "TYPE_1"); } TextPageLink pageLink1 = new TextPageLink(20, "ASSET_"); @@ -106,7 +108,7 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { List searchIds = new ArrayList<>(); for (int i = 0; i < 30; i++) { UUID assetId = UUIDs.timeBased(); - saveAsset(assetId, tenantId, customerId, "ASSET_" + i); + saveAsset(assetId, tenantId, customerId, "ASSET_" + i, "TYPE_1"); if (i % 3 == 0) { searchIds.add(assetId); } @@ -128,7 +130,7 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { for (int i = 0; i < 30; i++) { UUID assetId = UUIDs.timeBased(); UUID customerId = i%2 == 0 ? customerId1 : customerId2; - saveAsset(assetId, tenantId, customerId, "ASSET_" + i); + saveAsset(assetId, tenantId, customerId, "ASSET_" + i, "TYPE_1"); if (i % 3 == 0) { searchIds.add(assetId); } @@ -150,8 +152,8 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { UUID customerId1 = UUIDs.timeBased(); UUID customerId2 = UUIDs.timeBased(); String name = "TEST_ASSET"; - saveAsset(assetId1, tenantId1, customerId1, name); - saveAsset(assetId2, tenantId2, customerId2, name); + saveAsset(assetId1, tenantId1, customerId1, name, "TYPE_1"); + saveAsset(assetId2, tenantId2, customerId2, name, "TYPE_1"); Optional assetOpt1 = assetDao.findAssetsByTenantIdAndName(tenantId2, name); assertTrue("Optional expected to be non-empty", assetOpt1.isPresent()); @@ -161,13 +163,61 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { assertFalse("Optional expected to be empty", assetOpt2.isPresent()); } - private void saveAsset(UUID id, UUID tenantId, UUID customerId, String name) { + @Test + public void testFindAssetsByTenantIdAndType() { + // TODO: implement + } + + @Test + public void testFindAssetsByTenantIdAndCustomerIdAndType() { + // TODO: implement + } + + @Test + public void testFindTenantAssetTypesAsync() throws ExecutionException, InterruptedException { + UUID assetId1 = UUIDs.timeBased(); + UUID assetId2 = UUIDs.timeBased(); + UUID tenantId1 = UUIDs.timeBased(); + UUID tenantId2 = UUIDs.timeBased(); + UUID customerId1 = UUIDs.timeBased(); + UUID customerId2 = UUIDs.timeBased(); + saveAsset(UUIDs.timeBased(), tenantId1, customerId1, "TEST_ASSET_1", "TYPE_1"); + saveAsset(UUIDs.timeBased(), tenantId1, customerId1, "TEST_ASSET_2", "TYPE_1"); + saveAsset(UUIDs.timeBased(), tenantId1, customerId1, "TEST_ASSET_3", "TYPE_2"); + saveAsset(UUIDs.timeBased(), tenantId1, customerId1, "TEST_ASSET_4", "TYPE_3"); + saveAsset(UUIDs.timeBased(), tenantId1, customerId1, "TEST_ASSET_5", "TYPE_3"); + saveAsset(UUIDs.timeBased(), tenantId1, customerId1, "TEST_ASSET_6", "TYPE_3"); + + saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_7", "TYPE_4"); + saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_8", "TYPE_1"); + saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_9", "TYPE_1"); + + ListenableFuture> tenantAssetTypesFuture = assetDao.findTenantAssetTypesAsync(); + List tenantAssetTypes = tenantAssetTypesFuture.get(); + assertNotNull(tenantAssetTypes); + List tenant1Types = tenantAssetTypes.stream().filter(t -> t.getTenantId().getId().equals(tenantId1)).collect(Collectors.toList()); + List tenant2Types = tenantAssetTypes.stream().filter(t -> t.getTenantId().getId().equals(tenantId2)).collect(Collectors.toList()); + + assertEquals(3, tenant1Types.size()); + assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_1"))); + assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_2"))); + assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_3"))); + assertFalse(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_4"))); + + assertEquals(2, tenant2Types.size()); + assertTrue(tenant2Types.stream().anyMatch(t -> t.getType().equals("TYPE_1"))); + assertTrue(tenant2Types.stream().anyMatch(t -> t.getType().equals("TYPE_4"))); + assertFalse(tenant2Types.stream().anyMatch(t -> t.getType().equals("TYPE_2"))); + assertFalse(tenant2Types.stream().anyMatch(t -> t.getType().equals("TYPE_3"))); + } + + private void saveAsset(UUID id, UUID tenantId, UUID customerId, String name, String type) { Asset asset = new Asset(); asset.setId(new AssetId(id)); asset.setTenantId(new TenantId(tenantId)); asset.setCustomerId(new CustomerId(customerId)); asset.setName(name); - + asset.setType(type); assetDao.save(asset); } }