diff --git a/application/src/main/data/upgrade/1.3.0/schema_update.cql b/application/src/main/data/upgrade/1.3.0/schema_update.cql index 40706142e5..1e4302db3a 100644 --- a/application/src/main/data/upgrade/1.3.0/schema_update.cql +++ b/application/src/main/data/upgrade/1.3.0/schema_update.cql @@ -69,13 +69,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS - SELECT * - from thingsboard.device - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL - PRIMARY KEY ( (type, tenant_id), id, customer_id) - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); - DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_name; DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_search_text; DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_by_type_and_search_text; @@ -131,12 +124,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS - SELECT * - from thingsboard.asset - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL - PRIMARY KEY ( (type, tenant_id), id, customer_id) - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); +CREATE TABLE IF NOT EXISTS thingsboard.entity_subtype ( + tenant_id timeuuid, + entity_type text, // (DEVICE, ASSET) + type text, + PRIMARY KEY (tenant_id, entity_type, type) +); CREATE TABLE IF NOT EXISTS thingsboard.alarm ( id timeuuid, diff --git a/application/src/main/java/org/thingsboard/server/controller/AssetController.java b/application/src/main/java/org/thingsboard/server/controller/AssetController.java index dd43e1c4da..2857874da0 100644 --- a/application/src/main/java/org/thingsboard/server/controller/AssetController.java +++ b/application/src/main/java/org/thingsboard/server/controller/AssetController.java @@ -20,8 +20,8 @@ import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntitySubtype; 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; @@ -246,11 +246,11 @@ public class AssetController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/asset/types", method = RequestMethod.GET) @ResponseBody - public List getAssetTypes() throws ThingsboardException { + public List getAssetTypes() throws ThingsboardException { try { SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); - ListenableFuture> assetTypes = assetService.findAssetTypesByTenantId(tenantId); + ListenableFuture> assetTypes = assetService.findAssetTypesByTenantId(tenantId); return checkNotNull(assetTypes.get()); } catch (Exception e) { throw handleException(e); diff --git a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java index f0cde3316f..68b29b85e8 100644 --- a/application/src/main/java/org/thingsboard/server/controller/DeviceController.java +++ b/application/src/main/java/org/thingsboard/server/controller/DeviceController.java @@ -21,7 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.TenantDeviceType; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; @@ -283,11 +283,11 @@ public class DeviceController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/device/types", method = RequestMethod.GET) @ResponseBody - public List getDeviceTypes() throws ThingsboardException { + public List getDeviceTypes() throws ThingsboardException { try { SecurityUser user = getCurrentUser(); TenantId tenantId = user.getTenantId(); - ListenableFuture> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId); + ListenableFuture> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId); return checkNotNull(deviceTypes.get()); } catch (Exception e) { throw handleException(e); diff --git a/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java b/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java index 4e769f7fb6..83f1435378 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java +++ b/application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java @@ -64,26 +64,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService { log.info("Dumping devices ..."); Path devicesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device", - new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info"}, + new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"}, + new String[]{"", "", "", "", "", "", "default"}, "tb-devices"); - if (devicesDump != null) { - CassandraDbHelper.appendToEndOfLine(devicesDump, "default"); - } log.info("Devices dumped."); log.info("Dumping assets ..."); Path assetsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset", new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"}, + new String[]{"", "", "", "", "", "", "default"}, "tb-assets"); log.info("Assets dumped."); log.info("Dumping relations ..."); Path relationsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "relation", - new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info"}, + new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info", "relation_type_group"}, + new String[]{"", "", "", "", "", "", "COMMON"}, "tb-relations"); - if (relationsDump != null) { - CassandraDbHelper.appendToEndOfLine(relationsDump, "COMMON"); - } log.info("Relations dumped."); log.info("Updating schema ..."); @@ -101,6 +98,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService { } log.info("Devices restored."); + log.info("Dumping device types ..."); + Path deviceTypesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device", + new String[]{"tenant_id", "type"}, + new String[]{"", ""}, + "tb-device-types"); + if (deviceTypesDump != null) { + CassandraDbHelper.appendToEndOfLine(deviceTypesDump, "DEVICE"); + } + log.info("Device types dumped."); + log.info("Loading device types ..."); + if (deviceTypesDump != null) { + CassandraDbHelper.loadCf(ks, cluster.getSession(), "entity_subtype", + new String[]{"tenant_id", "type", "entity_type"}, deviceTypesDump); + Files.deleteIfExists(deviceTypesDump); + } + log.info("Device types loaded."); + log.info("Restoring assets ..."); if (assetsDump != null) { CassandraDbHelper.loadCf(ks, cluster.getSession(), "asset", @@ -109,6 +123,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService { } log.info("Assets restored."); + log.info("Dumping asset types ..."); + Path assetTypesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset", + new String[]{"tenant_id", "type"}, + new String[]{"", ""}, + "tb-asset-types"); + if (assetTypesDump != null) { + CassandraDbHelper.appendToEndOfLine(assetTypesDump, "ASSET"); + } + log.info("Asset types dumped."); + log.info("Loading asset types ..."); + if (assetTypesDump != null) { + CassandraDbHelper.loadCf(ks, cluster.getSession(), "entity_subtype", + new String[]{"tenant_id", "type", "entity_type"}, assetTypesDump); + Files.deleteIfExists(assetTypesDump); + } + log.info("Asset types loaded."); + log.info("Restoring relations ..."); if (relationsDump != null) { CassandraDbHelper.loadCf(ks, cluster.getSession(), "relation", diff --git a/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java b/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java index 4a92db212b..0a411f65a9 100644 --- a/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java +++ b/application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java @@ -33,7 +33,7 @@ public class CassandraDbHelper { private static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N"); public static Path dumpCfIfExists(KeyspaceMetadata ks, Session session, String cfName, - String[] columns, String dumpPrefix) throws Exception { + String[] columns, String[] defaultValues, String dumpPrefix) throws Exception { if (ks.getTable(cfName) != null) { Path dumpFile = Files.createTempFile(dumpPrefix, null); Files.deleteIfExists(dumpFile); @@ -45,7 +45,7 @@ public class CassandraDbHelper { while (iter.hasNext()) { Row row = iter.next(); if (row != null) { - dumpRow(row, columns, csvPrinter); + dumpRow(row, columns, defaultValues, csvPrinter); } } } @@ -89,18 +89,25 @@ public class CassandraDbHelper { } - private static void dumpRow(Row row, String[] columns, CSVPrinter csvPrinter) throws Exception { + private static void dumpRow(Row row, String[] columns, String[] defaultValues, CSVPrinter csvPrinter) throws Exception { List record = new ArrayList<>(); - for (String column : columns) { - record.add(getColumnValue(column, row)); + for (int i=0;i -1) { + String str; DataType type = row.getColumnDefinitions().getType(index); try { if (row.isNull(index)) { @@ -123,8 +130,10 @@ public class CassandraDbHelper { } catch (Exception e) { str = ""; } + return str; + } else { + return defaultValue; } - return str; } private static String createInsertStatement(String cfName, String[] columns) { diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java index 1350aaed4a..fb2e720b89 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java @@ -15,30 +15,31 @@ */ package org.thingsboard.server.controller; -import static org.hamcrest.Matchers.containsString; -import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - +import com.datastax.driver.core.utils.UUIDs; +import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.lang3.RandomStringUtils; -import org.thingsboard.server.common.data.*; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.Tenant; +import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.common.data.asset.TenantAssetType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.ModelConstants; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import com.datastax.driver.core.utils.UUIDs; -import com.fasterxml.jackson.core.type.TypeReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.hamcrest.Matchers.containsString; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; public abstract class BaseAssetControllerTest extends AbstractControllerTest { @@ -128,8 +129,8 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { asset.setType("typeA"); assets.add(doPost("/api/asset", asset, Asset.class)); } - List assetTypes = doGetTyped("/api/asset/types", - new TypeReference>(){}); + List assetTypes = doGetTyped("/api/asset/types", + new TypeReference>(){}); Assert.assertNotNull(assetTypes); Assert.assertEquals(3, assetTypes.size()); diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java index 3713fc45a1..f8da8fc9a6 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java @@ -140,8 +140,8 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { device.setType("typeA"); devices.add(doPost("/api/device", device, Device.class)); } - List deviceTypes = doGetTyped("/api/device/types", - new TypeReference>(){}); + List deviceTypes = doGetTyped("/api/device/types", + new TypeReference>(){}); Assert.assertNotNull(deviceTypes); Assert.assertEquals(3, deviceTypes.size()); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/TenantDeviceType.java b/common/data/src/main/java/org/thingsboard/server/common/data/EntitySubtype.java similarity index 56% rename from common/data/src/main/java/org/thingsboard/server/common/data/TenantDeviceType.java rename to common/data/src/main/java/org/thingsboard/server/common/data/EntitySubtype.java index d611a2507b..21bdf1e842 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/TenantDeviceType.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/EntitySubtype.java @@ -17,27 +17,21 @@ package org.thingsboard.server.common.data; import org.thingsboard.server.common.data.id.TenantId; -public class TenantDeviceType { +public class EntitySubtype { - private static final long serialVersionUID = 8057240243859922101L; + private static final long serialVersionUID = 8057240243059922101L; - private String type; private TenantId tenantId; + private EntityType entityType; + private String type; - public TenantDeviceType() { + public EntitySubtype() { super(); } - public TenantDeviceType(String type, TenantId tenantId) { - this.type = type; + public EntitySubtype(TenantId tenantId, EntityType entityType, String type) { this.tenantId = tenantId; - } - - public String getType() { - return type; - } - - public void setType(String type) { + this.entityType = entityType; this.type = type; } @@ -49,31 +43,52 @@ public class TenantDeviceType { this.tenantId = tenantId; } - @Override - public int hashCode() { - int result = type != null ? type.hashCode() : 0; - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0); - return result; + public EntityType getEntityType() { + return entityType; + } + + public void setEntityType(EntityType entityType) { + this.entityType = entityType; } + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - TenantDeviceType that = (TenantDeviceType) o; + EntitySubtype that = (EntitySubtype) o; - if (type != null ? !type.equals(that.type) : that.type != null) return false; - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null; + if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false; + if (entityType != that.entityType) return false; + return type != null ? type.equals(that.type) : that.type == null; } + @Override + public int hashCode() { + int result = tenantId != null ? tenantId.hashCode() : 0; + result = 31 * result + (entityType != null ? entityType.hashCode() : 0); + result = 31 * result + (type != null ? type.hashCode() : 0); + return result; + } + @Override public String toString() { - final StringBuilder sb = new StringBuilder("TenantDeviceType{"); - sb.append("type='").append(type).append('\''); - sb.append(", tenantId=").append(tenantId); + final StringBuilder sb = new StringBuilder("EntitySubtype{"); + sb.append("tenantId=").append(tenantId); + sb.append(", entityType=").append(entityType); + sb.append(", type='").append(type).append('\''); sb.append('}'); return sb.toString(); } + } 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 deleted file mode 100644 index b7cf5f9ac0..0000000000 --- a/common/data/src/main/java/org/thingsboard/server/common/data/asset/TenantAssetType.java +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.common.data.asset; - -import org.thingsboard.server.common.data.UUIDConverter; -import org.thingsboard.server.common.data.id.TenantId; - -import java.util.UUID; - -public class TenantAssetType { - - private static final long serialVersionUID = 8057290243855622101L; - - private String type; - private TenantId tenantId; - - public TenantAssetType() { - super(); - } - - public TenantAssetType(String type, TenantId tenantId) { - this.type = type; - this.tenantId = tenantId; - } - - public TenantAssetType(String type, UUID tenantId) { - this.type = type; - this.tenantId = new TenantId(tenantId); - } - - public TenantAssetType(String type, String tenantId) { - this.type = type; - this.tenantId = new TenantId(UUIDConverter.fromString(tenantId)); - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public TenantId getTenantId() { - return tenantId; - } - - public void setTenantId(TenantId tenantId) { - this.tenantId = tenantId; - } - - @Override - public int hashCode() { - int result = type != null ? type.hashCode() : 0; - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0); - return result; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TenantAssetType that = (TenantAssetType) o; - - if (type != null ? !type.equals(that.type) : that.type != null) return false; - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null; - - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("TenantAssetType{"); - sb.append("type='").append(type).append('\''); - sb.append(", tenantId=").append(tenantId); - sb.append('}'); - return sb.toString(); - } -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java index 73211fedfe..f953335486 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java @@ -16,8 +16,8 @@ package org.thingsboard.server.dao.asset; import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.common.data.asset.TenantAssetType; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.Dao; @@ -112,6 +112,6 @@ public interface AssetDao extends Dao { * * @return the list of tenant asset type objects */ - ListenableFuture> findTenantAssetTypesAsync(); + ListenableFuture> findTenantAssetTypesAsync(UUID tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java index 25baeda0d5..214ef15b48 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java @@ -16,8 +16,8 @@ package org.thingsboard.server.dao.asset; import com.google.common.util.concurrent.ListenableFuture; +import org.thingsboard.server.common.data.EntitySubtype; 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; @@ -61,5 +61,5 @@ public interface AssetService { ListenableFuture> findAssetsByQuery(AssetSearchQuery query); - ListenableFuture> findAssetTypesByTenantId(TenantId tenantId); + ListenableFuture> findAssetTypesByTenantId(TenantId tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java index 3a2805cff9..615cdf8b1a 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java @@ -25,10 +25,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.Tenant; 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.EntityId; @@ -217,22 +217,15 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ } @Override - public ListenableFuture> findAssetTypesByTenantId(TenantId tenantId) { + public ListenableFuture> findAssetTypesByTenantId(TenantId tenantId) { log.trace("Executing findAssetTypesByTenantId, tenantId [{}]", tenantId); validateId(tenantId, "Incorrect tenantId " + tenantId); - ListenableFuture> tenantAssetTypeEntities = assetDao.findTenantAssetTypesAsync(); - ListenableFuture> tenantAssetTypes = Futures.transform(tenantAssetTypeEntities, - (Function, List>) assetTypeEntities -> { - List assetTypes = new ArrayList<>(); - for (TenantAssetType assetType : assetTypeEntities) { - if (assetType.getTenantId().equals(tenantId)) { - assetTypes.add(assetType); - } - } - assetTypes.sort(Comparator.comparing(TenantAssetType::getType)); + ListenableFuture> tenantAssetTypes = assetDao.findTenantAssetTypesAsync(tenantId.getId()); + return Futures.transform(tenantAssetTypes, + (Function, List>) assetTypes -> { + assetTypes.sort(Comparator.comparing(EntitySubtype::getType)); return assetTypes; }); - return tenantAssetTypes; } private DataValidator assetValidator = diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/CassandraAssetDao.java b/dao/src/main/java/org/thingsboard/server/dao/asset/CassandraAssetDao.java index 339c9ea4c3..d6c6ca431d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/asset/CassandraAssetDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/asset/CassandraAssetDao.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSetFuture; +import com.datastax.driver.core.Statement; import com.datastax.driver.core.querybuilder.Select; import com.datastax.driver.mapping.Result; import com.google.common.base.Function; @@ -24,11 +25,12 @@ import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.common.data.asset.TenantAssetType; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.DaoUtil; -import org.thingsboard.server.dao.model.TenantAssetTypeEntity; +import org.thingsboard.server.dao.model.EntitySubtypeEntity; import org.thingsboard.server.dao.model.nosql.AssetEntity; import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; import org.thingsboard.server.dao.util.NoSqlDao; @@ -54,6 +56,16 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao findAssetsByTenantId(UUID tenantId, TextPageLink pageLink) { log.debug("Try to find assets by tenantId [{}] and pageLink [{}]", tenantId, pageLink); @@ -130,36 +142,29 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao> findTenantAssetTypesAsync() { - Select statement = select().distinct().column(ASSET_TYPE_PROPERTY).column(ASSET_TENANT_ID_PROPERTY).from(ASSET_TYPES_BY_TENANT_VIEW_NAME); - statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()); - ResultSetFuture resultSetFuture = getSession().executeAsync(statement); - ListenableFuture> result = Futures.transform(resultSetFuture, new Function>() { + public ListenableFuture> findTenantAssetTypesAsync(UUID tenantId) { + Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME); + Select.Where query = select.where(); + query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId)); + query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.ASSET)); + query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()); + ResultSetFuture resultSetFuture = getSession().executeAsync(query); + return Futures.transform(resultSetFuture, new Function>() { @Nullable @Override - public List apply(@Nullable ResultSet resultSet) { - Result result = cluster.getMapper(TenantAssetTypeEntity.class).map(resultSet); + public List apply(@Nullable ResultSet resultSet) { + Result result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet); if (result != null) { - return result.all(); + List entitySubtypes = new ArrayList<>(); + result.all().forEach((entitySubtypeEntity) -> + entitySubtypes.add(entitySubtypeEntity.toEntitySubtype()) + ); + return entitySubtypes; } else { return Collections.emptyList(); } } }); - return Futures.transform(result, new Function, List>() { - @Nullable - @Override - public List apply(@Nullable List entityList) { - List list = Collections.emptyList(); - if (entityList != null && !entityList.isEmpty()) { - list = new ArrayList<>(); - for (TenantAssetTypeEntity object : entityList) { - list.add(object.toTenantAssetType()); - } - } - return list; - } - }); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/CassandraDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/device/CassandraDeviceDao.java index a0d4fe1308..9c3a4bbb08 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/CassandraDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/CassandraDeviceDao.java @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device; import com.datastax.driver.core.ResultSet; import com.datastax.driver.core.ResultSetFuture; +import com.datastax.driver.core.Statement; import com.datastax.driver.core.querybuilder.Select; import com.datastax.driver.mapping.Result; import com.google.common.base.Function; @@ -25,10 +26,11 @@ import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.TenantDeviceType; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.DaoUtil; -import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; +import org.thingsboard.server.dao.model.EntitySubtypeEntity; import org.thingsboard.server.dao.model.nosql.DeviceEntity; import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; import org.thingsboard.server.dao.util.NoSqlDao; @@ -54,6 +56,16 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao findDevicesByTenantId(UUID tenantId, TextPageLink pageLink) { log.debug("Try to find devices by tenantId [{}] and pageLink [{}]", tenantId, pageLink); @@ -130,36 +142,29 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao> findTenantDeviceTypesAsync() { - Select statement = select().distinct().column(DEVICE_TYPE_PROPERTY).column(DEVICE_TENANT_ID_PROPERTY).from(DEVICE_TYPES_BY_TENANT_VIEW_NAME); - statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()); - ResultSetFuture resultSetFuture = getSession().executeAsync(statement); - ListenableFuture> result = Futures.transform(resultSetFuture, new Function>() { + public ListenableFuture> findTenantDeviceTypesAsync(UUID tenantId) { + Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME); + Select.Where query = select.where(); + query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId)); + query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.DEVICE)); + query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel()); + ResultSetFuture resultSetFuture = getSession().executeAsync(query); + return Futures.transform(resultSetFuture, new Function>() { @Nullable @Override - public List apply(@Nullable ResultSet resultSet) { - Result result = cluster.getMapper(TenantDeviceTypeEntity.class).map(resultSet); + public List apply(@Nullable ResultSet resultSet) { + Result result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet); if (result != null) { - return result.all(); + List entitySubtypes = new ArrayList<>(); + result.all().forEach((entitySubtypeEntity) -> + entitySubtypes.add(entitySubtypeEntity.toEntitySubtype()) + ); + return entitySubtypes; } else { return Collections.emptyList(); } } }); - return Futures.transform(result, new Function, List>() { - @Nullable - @Override - public List apply(@Nullable List entityList) { - List list = Collections.emptyList(); - if (entityList != null && !entityList.isEmpty()) { - list = new ArrayList<>(); - for (TenantDeviceTypeEntity object : entityList) { - list.add(object.toTenantDeviceType()); - } - } - return list; - } - }); } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java index a6d785e4a3..c0c17449a5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.TenantDeviceType; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.Dao; @@ -113,5 +113,5 @@ public interface DeviceDao extends Dao { * * @return the list of tenant device type objects */ - ListenableFuture> findTenantDeviceTypesAsync(); + ListenableFuture> findTenantDeviceTypesAsync(UUID tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceService.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceService.java index 3e7b6af7ad..cd56fefbdb 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceService.java @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device; import com.google.common.util.concurrent.ListenableFuture; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.TenantDeviceType; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; @@ -61,6 +61,6 @@ public interface DeviceService { ListenableFuture> findDevicesByQuery(DeviceSearchQuery query); - ListenableFuture> findDeviceTypesByTenantId(TenantId tenantId); + ListenableFuture> findDeviceTypesByTenantId(TenantId tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java index 7535967196..e1056f8ef3 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java @@ -237,22 +237,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe } @Override - public ListenableFuture> findDeviceTypesByTenantId(TenantId tenantId) { + public ListenableFuture> findDeviceTypesByTenantId(TenantId tenantId) { log.trace("Executing findDeviceTypesByTenantId, tenantId [{}]", tenantId); validateId(tenantId, "Incorrect tenantId " + tenantId); - ListenableFuture> tenantDeviceTypeEntities = deviceDao.findTenantDeviceTypesAsync(); - ListenableFuture> tenantDeviceTypes = Futures.transform(tenantDeviceTypeEntities, - (Function, List>) deviceTypeEntities -> { - List deviceTypes = new ArrayList<>(); - for (TenantDeviceType deviceType : deviceTypeEntities) { - if (deviceType.getTenantId().equals(tenantId)) { - deviceTypes.add(deviceType); - } - } - deviceTypes.sort(Comparator.comparing(TenantDeviceType::getType)); + ListenableFuture> tenantDeviceTypes = deviceDao.findTenantDeviceTypesAsync(tenantId.getId()); + return Futures.transform(tenantDeviceTypes, + (Function, List>) deviceTypes -> { + deviceTypes.sort(Comparator.comparing(EntitySubtype::getType)); return deviceTypes; - }); - return tenantDeviceTypes; + }); } private DataValidator deviceValidator = diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/EntitySubtypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/EntitySubtypeEntity.java new file mode 100644 index 0000000000..77983d34b7 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/model/EntitySubtypeEntity.java @@ -0,0 +1,123 @@ +/** + * Copyright © 2016-2017 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.thingsboard.server.dao.model; + +import com.datastax.driver.mapping.annotations.Column; +import com.datastax.driver.mapping.annotations.PartitionKey; +import com.datastax.driver.mapping.annotations.Table; +import com.datastax.driver.mapping.annotations.Transient; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.model.type.EntityTypeCodec; + +import java.util.UUID; + +import static org.thingsboard.server.dao.model.ModelConstants.*; + +@Table(name = ENTITY_SUBTYPE_COLUMN_FAMILY_NAME) +public class EntitySubtypeEntity { + + @Transient + private static final long serialVersionUID = -1268181961886910152L; + + @PartitionKey(value = 0) + @Column(name = ENTITY_SUBTYPE_TENANT_ID_PROPERTY) + private UUID tenantId; + + @PartitionKey(value = 1) + @Column(name = ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, codec = EntityTypeCodec.class) + private EntityType entityType; + + @PartitionKey(value = 2) + @Column(name = ENTITY_SUBTYPE_TYPE_PROPERTY) + private String type; + + public EntitySubtypeEntity() { + super(); + } + + public EntitySubtypeEntity(EntitySubtype entitySubtype) { + this.tenantId = entitySubtype.getTenantId().getId(); + this.entityType = entitySubtype.getEntityType(); + this.type = entitySubtype.getType(); + } + + public UUID getTenantId() { + return tenantId; + } + + public void setTenantId(UUID tenantId) { + this.tenantId = tenantId; + } + + public EntityType getEntityType() { + return entityType; + } + + public void setEntityType(EntityType entityType) { + this.entityType = entityType; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + EntitySubtypeEntity that = (EntitySubtypeEntity) o; + + if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false; + if (entityType != that.entityType) return false; + return type != null ? type.equals(that.type) : that.type == null; + + } + + @Override + public int hashCode() { + int result = tenantId != null ? tenantId.hashCode() : 0; + result = 31 * result + (entityType != null ? entityType.hashCode() : 0); + result = 31 * result + (type != null ? type.hashCode() : 0); + return result; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("EntitySubtypeEntity{"); + sb.append("tenantId=").append(tenantId); + sb.append(", entityType=").append(entityType); + sb.append(", type='").append(type).append('\''); + sb.append('}'); + return sb.toString(); + } + + public EntitySubtype toEntitySubtype() { + EntitySubtype entitySubtype = new EntitySubtype(); + entitySubtype.setTenantId(new TenantId(tenantId)); + entitySubtype.setEntityType(entityType); + entitySubtype.setType(type); + return entitySubtype; + } +} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java index 1bf88bea82..194a41c7b8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java @@ -150,6 +150,14 @@ public class ModelConstants { public static final String ASSET_BY_TENANT_AND_NAME_VIEW_NAME = "asset_by_tenant_and_name"; public static final String ASSET_TYPES_BY_TENANT_VIEW_NAME = "asset_types_by_tenant"; + /** + * Cassandra entity_subtype constants. + */ + public static final String ENTITY_SUBTYPE_COLUMN_FAMILY_NAME = "entity_subtype"; + public static final String ENTITY_SUBTYPE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY; + public static final String ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY = "entity_type"; + public static final String ENTITY_SUBTYPE_TYPE_PROPERTY = "type"; + /** * Cassandra alarm constants. */ diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/TenantAssetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/TenantAssetTypeEntity.java deleted file mode 100644 index 36361ef2b4..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/model/TenantAssetTypeEntity.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.thingsboard.server.dao.model; - -import com.datastax.driver.mapping.annotations.Column; -import com.datastax.driver.mapping.annotations.PartitionKey; -import com.datastax.driver.mapping.annotations.Table; -import com.datastax.driver.mapping.annotations.Transient; -import org.thingsboard.server.common.data.asset.TenantAssetType; -import org.thingsboard.server.common.data.id.TenantId; - -import java.util.UUID; - -import static org.thingsboard.server.dao.model.ModelConstants.*; - -@Table(name = ASSET_TYPES_BY_TENANT_VIEW_NAME) -public class TenantAssetTypeEntity { - - @Transient - private static final long serialVersionUID = -1268181161886910152L; - - @PartitionKey(value = 0) - @Column(name = ASSET_TYPE_PROPERTY) - private String type; - - @PartitionKey(value = 1) - @Column(name = ASSET_TENANT_ID_PROPERTY) - private UUID tenantId; - - public TenantAssetTypeEntity() { - super(); - } - - public TenantAssetTypeEntity(TenantAssetType tenantAssetType) { - this.type = tenantAssetType.getType(); - if (tenantAssetType.getTenantId() != null) { - this.tenantId = tenantAssetType.getTenantId().getId(); - } - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public UUID getTenantId() { - return tenantId; - } - - public void setTenantId(UUID tenantId) { - this.tenantId = tenantId; - } - - @Override - public int hashCode() { - int result = type != null ? type.hashCode() : 0; - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0); - return result; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TenantAssetTypeEntity that = (TenantAssetTypeEntity) o; - - if (type != null ? !type.equals(that.type) : that.type != null) return false; - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null; - - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("TenantAssetTypeEntity{"); - sb.append("type='").append(type).append('\''); - sb.append(", tenantId=").append(tenantId); - sb.append('}'); - return sb.toString(); - } - - public TenantAssetType toTenantAssetType() { - TenantAssetType tenantAssetType = new TenantAssetType(); - tenantAssetType.setType(type); - if (tenantId != null) { - tenantAssetType.setTenantId(new TenantId(tenantId)); - } - return tenantAssetType; - } -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/TenantDeviceTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/TenantDeviceTypeEntity.java deleted file mode 100644 index dad954c63f..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/model/TenantDeviceTypeEntity.java +++ /dev/null @@ -1,107 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.thingsboard.server.dao.model; - -import com.datastax.driver.mapping.annotations.Column; -import com.datastax.driver.mapping.annotations.PartitionKey; -import com.datastax.driver.mapping.annotations.Table; -import com.datastax.driver.mapping.annotations.Transient; -import org.thingsboard.server.common.data.TenantDeviceType; -import org.thingsboard.server.common.data.id.TenantId; - -import java.util.UUID; - -import static org.thingsboard.server.dao.model.ModelConstants.*; - -@Table(name = DEVICE_TYPES_BY_TENANT_VIEW_NAME) -public class TenantDeviceTypeEntity { - - @Transient - private static final long serialVersionUID = -1268181166886910152L; - - @PartitionKey(value = 0) - @Column(name = DEVICE_TYPE_PROPERTY) - private String type; - - @PartitionKey(value = 1) - @Column(name = DEVICE_TENANT_ID_PROPERTY) - private UUID tenantId; - - public TenantDeviceTypeEntity() { - super(); - } - - public TenantDeviceTypeEntity(TenantDeviceType tenantDeviceType) { - this.type = tenantDeviceType.getType(); - if (tenantDeviceType.getTenantId() != null) { - this.tenantId = tenantDeviceType.getTenantId().getId(); - } - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public UUID getTenantId() { - return tenantId; - } - - public void setTenantId(UUID tenantId) { - this.tenantId = tenantId; - } - - @Override - public int hashCode() { - int result = type != null ? type.hashCode() : 0; - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0); - return result; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - TenantDeviceTypeEntity that = (TenantDeviceTypeEntity) o; - - if (type != null ? !type.equals(that.type) : that.type != null) return false; - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null; - - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder("TenantDeviceTypeEntity{"); - sb.append("type='").append(type).append('\''); - sb.append(", tenantId=").append(tenantId); - sb.append('}'); - return sb.toString(); - } - - public TenantDeviceType toTenantDeviceType() { - TenantDeviceType tenantDeviceType = new TenantDeviceType(); - tenantDeviceType.setType(type); - if (tenantId != null) { - tenantDeviceType.setTenantId(new TenantId(tenantId)); - } - return tenantDeviceType; - } -} diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantDeviceTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantDeviceTypeEntity.java deleted file mode 100644 index a4f7256719..0000000000 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantDeviceTypeEntity.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright © 2016-2017 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.thingsboard.server.dao.model.sql; - -import lombok.AllArgsConstructor; -import lombok.Data; - -@AllArgsConstructor -@Data -public class TenantDeviceTypeEntity { - private String tenantId; - private String type; -} 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 478c6efeb6..b0636f1e3a 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,7 +19,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; -import org.thingsboard.server.common.data.asset.TenantAssetType; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.dao.model.sql.AssetEntity; import org.thingsboard.server.dao.util.SqlDao; @@ -76,6 +77,7 @@ public interface AssetRepository extends CrudRepository { @Param("idOffset") String idOffset, Pageable pageable); - @Query("SELECT NEW org.thingsboard.server.common.data.asset.TenantAssetType(a.type, a.tenantId) FROM AssetEntity a GROUP BY a.tenantId, a.type") - List findTenantAssetTypes(); + @Query("SELECT DISTINCT a.type FROM AssetEntity a WHERE a.tenantId = :tenantId") + List findTenantAssetTypes(@Param("tenantId") String tenantId); + } 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 81ce691022..ea256e6a7d 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 @@ -20,8 +20,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.common.data.asset.TenantAssetType; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.asset.AssetDao; @@ -29,10 +31,7 @@ import org.thingsboard.server.dao.model.sql.AssetEntity; import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import org.thingsboard.server.dao.util.SqlDao; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.UUID; +import java.util.*; import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs; @@ -121,7 +120,18 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao im } @Override - public ListenableFuture> findTenantAssetTypesAsync() { - return service.submit(() -> assetRepository.findTenantAssetTypes()); + public ListenableFuture> findTenantAssetTypesAsync(UUID tenantId) { + return service.submit(() -> convertTenantAssetTypesToDto(tenantId, assetRepository.findTenantAssetTypes(fromTimeUUID(tenantId)))); + } + + private List convertTenantAssetTypesToDto(UUID tenantId, List types) { + List list = Collections.emptyList(); + if (types != null && !types.isEmpty()) { + list = new ArrayList<>(); + for (String type : types) { + list.add(new EntitySubtype(new TenantId(tenantId), EntityType.ASSET, type)); + } + } + return list; } } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java index 256f62343b..bcea4ce866 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java @@ -20,7 +20,6 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.query.Param; import org.thingsboard.server.dao.model.sql.DeviceEntity; -import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity; import org.thingsboard.server.dao.util.SqlDao; import java.util.List; @@ -72,8 +71,8 @@ public interface DeviceRepository extends CrudRepository { @Param("idOffset") String idOffset, Pageable pageable); - @Query("SELECT DISTINCT NEW org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity(d.tenantId, d.type) FROM DeviceEntity d") - List findTenantDeviceTypes(); + @Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId") + List findTenantDeviceTypes(@Param("tenantId") String tenantId); DeviceEntity findByTenantIdAndName(String tenantId, String name); diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index 4835c6c031..a3f02f8d43 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -21,14 +21,14 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; import org.thingsboard.server.common.data.Device; -import org.thingsboard.server.common.data.TenantDeviceType; +import org.thingsboard.server.common.data.EntitySubtype; +import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.UUIDConverter; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.device.DeviceDao; import org.thingsboard.server.dao.model.sql.DeviceEntity; -import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity; import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; import org.thingsboard.server.dao.util.SqlDao; @@ -120,16 +120,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao } @Override - public ListenableFuture> findTenantDeviceTypesAsync() { - return service.submit(() -> convertTenantDeviceTypeEntityToDto(deviceRepository.findTenantDeviceTypes())); + public ListenableFuture> findTenantDeviceTypesAsync(UUID tenantId) { + return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(fromTimeUUID(tenantId)))); } - private List convertTenantDeviceTypeEntityToDto(List entities) { - List list = Collections.emptyList(); - if (entities != null && !entities.isEmpty()) { + private List convertTenantDeviceTypesToDto(UUID tenantId, List types) { + List list = Collections.emptyList(); + if (types != null && !types.isEmpty()) { list = new ArrayList<>(); - for (TenantDeviceTypeEntity entity : entities) { - list.add(new TenantDeviceType(entity.getType(), new TenantId(UUIDConverter.fromString(entity.getTenantId())))); + for (String type : types) { + list.add(new EntitySubtype(new TenantId(tenantId), EntityType.DEVICE, type)); } } return list; diff --git a/dao/src/main/resources/cassandra/schema.cql b/dao/src/main/resources/cassandra/schema.cql index 71de6771af..dda80676e2 100644 --- a/dao/src/main/resources/cassandra/schema.cql +++ b/dao/src/main/resources/cassandra/schema.cql @@ -197,13 +197,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS - SELECT * - from thingsboard.device - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL - PRIMARY KEY ( (type, tenant_id), id, customer_id) - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); - CREATE TABLE IF NOT EXISTS thingsboard.device_credentials ( id timeuuid PRIMARY KEY, device_id timeuuid, @@ -270,12 +263,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS - SELECT * - from thingsboard.asset - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL - PRIMARY KEY ( (type, tenant_id), id, customer_id) - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); +CREATE TABLE IF NOT EXISTS thingsboard.entity_subtype ( + tenant_id timeuuid, + entity_type text, // (DEVICE, ASSET) + type text, + PRIMARY KEY (tenant_id, entity_type, type) +); CREATE TABLE IF NOT EXISTS thingsboard.alarm ( id timeuuid, diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAssetServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAssetServiceTest.java index 2dbf739f1b..6bcc74a2b2 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAssetServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAssetServiceTest.java @@ -22,9 +22,9 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.thingsboard.server.common.data.Customer; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.common.data.asset.TenantAssetType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; @@ -181,7 +181,7 @@ public abstract class BaseAssetServiceTest extends AbstractServiceTest { asset.setType("typeA"); assets.add(assetService.saveAsset(asset)); } - List assetTypes = assetService.findAssetTypesByTenantId(tenantId).get(); + List assetTypes = assetService.findAssetTypesByTenantId(tenantId).get(); Assert.assertNotNull(assetTypes); Assert.assertEquals(3, assetTypes.size()); Assert.assertEquals("typeA", assetTypes.get(0).getType()); diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java index addaf8fa53..0c35798f78 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java @@ -23,8 +23,8 @@ import org.junit.Before; import org.junit.Test; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Device; +import org.thingsboard.server.common.data.EntitySubtype; import org.thingsboard.server.common.data.Tenant; -import org.thingsboard.server.common.data.TenantDeviceType; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.page.TextPageData; @@ -191,7 +191,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { device.setType("typeA"); devices.add(deviceService.saveDevice(device)); } - List deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId).get(); + List deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId).get(); Assert.assertNotNull(deviceTypes); Assert.assertEquals(3, deviceTypes.size()); Assert.assertEquals("typeA", deviceTypes.get(0).getType()); 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 4be102e089..062f0e686f 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 @@ -19,8 +19,8 @@ import com.datastax.driver.core.utils.UUIDs; import com.google.common.util.concurrent.ListenableFuture; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.thingsboard.server.common.data.EntitySubtype; 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; @@ -33,12 +33,9 @@ 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; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; /** * Created by Valerii Sosliuk on 5/21/2017. @@ -192,11 +189,10 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { 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()); + List tenant1Types = assetDao.findTenantAssetTypesAsync(tenantId1).get(); + assertNotNull(tenant1Types); + List tenant2Types = assetDao.findTenantAssetTypesAsync(tenantId2).get(); + assertNotNull(tenant2Types); assertEquals(3, tenant1Types.size()); assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_1")));