Commit ac3e4429b8fe0f87a38f4a0def03a568edf06ae0

Authored by Igor Kulikov
1 parent 709280ef

Improve device/asset types management.

Showing 29 changed files with 319 additions and 475 deletions
@@ -69,13 +69,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an @@ -69,13 +69,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an
69 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) 69 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
70 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); 70 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
71 71
72 -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS  
73 - SELECT *  
74 - from thingsboard.device  
75 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL  
76 - PRIMARY KEY ( (type, tenant_id), id, customer_id)  
77 - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);  
78 -  
79 DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_name; 72 DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_name;
80 DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_search_text; 73 DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_search_text;
81 DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_by_type_and_search_text; 74 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 @@ -131,12 +124,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and
131 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) 124 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
132 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); 125 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
133 126
134 -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS  
135 - SELECT *  
136 - from thingsboard.asset  
137 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL  
138 - PRIMARY KEY ( (type, tenant_id), id, customer_id)  
139 - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); 127 +CREATE TABLE IF NOT EXISTS thingsboard.entity_subtype (
  128 + tenant_id timeuuid,
  129 + entity_type text, // (DEVICE, ASSET)
  130 + type text,
  131 + PRIMARY KEY (tenant_id, entity_type, type)
  132 +);
140 133
141 CREATE TABLE IF NOT EXISTS thingsboard.alarm ( 134 CREATE TABLE IF NOT EXISTS thingsboard.alarm (
142 id timeuuid, 135 id timeuuid,
@@ -20,8 +20,8 @@ import org.springframework.http.HttpStatus; @@ -20,8 +20,8 @@ import org.springframework.http.HttpStatus;
20 import org.springframework.security.access.prepost.PreAuthorize; 20 import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
22 import org.thingsboard.server.common.data.Customer; 22 import org.thingsboard.server.common.data.Customer;
  23 +import org.thingsboard.server.common.data.EntitySubtype;
23 import org.thingsboard.server.common.data.asset.Asset; 24 import org.thingsboard.server.common.data.asset.Asset;
24 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
25 import org.thingsboard.server.common.data.id.AssetId; 25 import org.thingsboard.server.common.data.id.AssetId;
26 import org.thingsboard.server.common.data.id.CustomerId; 26 import org.thingsboard.server.common.data.id.CustomerId;
27 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
@@ -246,11 +246,11 @@ public class AssetController extends BaseController { @@ -246,11 +246,11 @@ public class AssetController extends BaseController {
246 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 246 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
247 @RequestMapping(value = "/asset/types", method = RequestMethod.GET) 247 @RequestMapping(value = "/asset/types", method = RequestMethod.GET)
248 @ResponseBody 248 @ResponseBody
249 - public List<TenantAssetType> getAssetTypes() throws ThingsboardException { 249 + public List<EntitySubtype> getAssetTypes() throws ThingsboardException {
250 try { 250 try {
251 SecurityUser user = getCurrentUser(); 251 SecurityUser user = getCurrentUser();
252 TenantId tenantId = user.getTenantId(); 252 TenantId tenantId = user.getTenantId();
253 - ListenableFuture<List<TenantAssetType>> assetTypes = assetService.findAssetTypesByTenantId(tenantId); 253 + ListenableFuture<List<EntitySubtype>> assetTypes = assetService.findAssetTypesByTenantId(tenantId);
254 return checkNotNull(assetTypes.get()); 254 return checkNotNull(assetTypes.get());
255 } catch (Exception e) { 255 } catch (Exception e) {
256 throw handleException(e); 256 throw handleException(e);
@@ -21,7 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize; @@ -21,7 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
21 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
22 import org.thingsboard.server.common.data.Customer; 22 import org.thingsboard.server.common.data.Customer;
23 import org.thingsboard.server.common.data.Device; 23 import org.thingsboard.server.common.data.Device;
24 -import org.thingsboard.server.common.data.TenantDeviceType; 24 +import org.thingsboard.server.common.data.EntitySubtype;
25 import org.thingsboard.server.common.data.id.CustomerId; 25 import org.thingsboard.server.common.data.id.CustomerId;
26 import org.thingsboard.server.common.data.id.DeviceId; 26 import org.thingsboard.server.common.data.id.DeviceId;
27 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
@@ -283,11 +283,11 @@ public class DeviceController extends BaseController { @@ -283,11 +283,11 @@ public class DeviceController extends BaseController {
283 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 283 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
284 @RequestMapping(value = "/device/types", method = RequestMethod.GET) 284 @RequestMapping(value = "/device/types", method = RequestMethod.GET)
285 @ResponseBody 285 @ResponseBody
286 - public List<TenantDeviceType> getDeviceTypes() throws ThingsboardException { 286 + public List<EntitySubtype> getDeviceTypes() throws ThingsboardException {
287 try { 287 try {
288 SecurityUser user = getCurrentUser(); 288 SecurityUser user = getCurrentUser();
289 TenantId tenantId = user.getTenantId(); 289 TenantId tenantId = user.getTenantId();
290 - ListenableFuture<List<TenantDeviceType>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId); 290 + ListenableFuture<List<EntitySubtype>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId);
291 return checkNotNull(deviceTypes.get()); 291 return checkNotNull(deviceTypes.get());
292 } catch (Exception e) { 292 } catch (Exception e) {
293 throw handleException(e); 293 throw handleException(e);
@@ -64,26 +64,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService { @@ -64,26 +64,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
64 64
65 log.info("Dumping devices ..."); 65 log.info("Dumping devices ...");
66 Path devicesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device", 66 Path devicesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device",
67 - new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info"}, 67 + new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"},
  68 + new String[]{"", "", "", "", "", "", "default"},
68 "tb-devices"); 69 "tb-devices");
69 - if (devicesDump != null) {  
70 - CassandraDbHelper.appendToEndOfLine(devicesDump, "default");  
71 - }  
72 log.info("Devices dumped."); 70 log.info("Devices dumped.");
73 71
74 log.info("Dumping assets ..."); 72 log.info("Dumping assets ...");
75 Path assetsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset", 73 Path assetsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset",
76 new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"}, 74 new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"},
  75 + new String[]{"", "", "", "", "", "", "default"},
77 "tb-assets"); 76 "tb-assets");
78 log.info("Assets dumped."); 77 log.info("Assets dumped.");
79 78
80 log.info("Dumping relations ..."); 79 log.info("Dumping relations ...");
81 Path relationsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "relation", 80 Path relationsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "relation",
82 - new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info"}, 81 + new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info", "relation_type_group"},
  82 + new String[]{"", "", "", "", "", "", "COMMON"},
83 "tb-relations"); 83 "tb-relations");
84 - if (relationsDump != null) {  
85 - CassandraDbHelper.appendToEndOfLine(relationsDump, "COMMON");  
86 - }  
87 log.info("Relations dumped."); 84 log.info("Relations dumped.");
88 85
89 log.info("Updating schema ..."); 86 log.info("Updating schema ...");
@@ -101,6 +98,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService { @@ -101,6 +98,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
101 } 98 }
102 log.info("Devices restored."); 99 log.info("Devices restored.");
103 100
  101 + log.info("Dumping device types ...");
  102 + Path deviceTypesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device",
  103 + new String[]{"tenant_id", "type"},
  104 + new String[]{"", ""},
  105 + "tb-device-types");
  106 + if (deviceTypesDump != null) {
  107 + CassandraDbHelper.appendToEndOfLine(deviceTypesDump, "DEVICE");
  108 + }
  109 + log.info("Device types dumped.");
  110 + log.info("Loading device types ...");
  111 + if (deviceTypesDump != null) {
  112 + CassandraDbHelper.loadCf(ks, cluster.getSession(), "entity_subtype",
  113 + new String[]{"tenant_id", "type", "entity_type"}, deviceTypesDump);
  114 + Files.deleteIfExists(deviceTypesDump);
  115 + }
  116 + log.info("Device types loaded.");
  117 +
104 log.info("Restoring assets ..."); 118 log.info("Restoring assets ...");
105 if (assetsDump != null) { 119 if (assetsDump != null) {
106 CassandraDbHelper.loadCf(ks, cluster.getSession(), "asset", 120 CassandraDbHelper.loadCf(ks, cluster.getSession(), "asset",
@@ -109,6 +123,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService { @@ -109,6 +123,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
109 } 123 }
110 log.info("Assets restored."); 124 log.info("Assets restored.");
111 125
  126 + log.info("Dumping asset types ...");
  127 + Path assetTypesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset",
  128 + new String[]{"tenant_id", "type"},
  129 + new String[]{"", ""},
  130 + "tb-asset-types");
  131 + if (assetTypesDump != null) {
  132 + CassandraDbHelper.appendToEndOfLine(assetTypesDump, "ASSET");
  133 + }
  134 + log.info("Asset types dumped.");
  135 + log.info("Loading asset types ...");
  136 + if (assetTypesDump != null) {
  137 + CassandraDbHelper.loadCf(ks, cluster.getSession(), "entity_subtype",
  138 + new String[]{"tenant_id", "type", "entity_type"}, assetTypesDump);
  139 + Files.deleteIfExists(assetTypesDump);
  140 + }
  141 + log.info("Asset types loaded.");
  142 +
112 log.info("Restoring relations ..."); 143 log.info("Restoring relations ...");
113 if (relationsDump != null) { 144 if (relationsDump != null) {
114 CassandraDbHelper.loadCf(ks, cluster.getSession(), "relation", 145 CassandraDbHelper.loadCf(ks, cluster.getSession(), "relation",
@@ -33,7 +33,7 @@ public class CassandraDbHelper { @@ -33,7 +33,7 @@ public class CassandraDbHelper {
33 private static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N"); 33 private static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N");
34 34
35 public static Path dumpCfIfExists(KeyspaceMetadata ks, Session session, String cfName, 35 public static Path dumpCfIfExists(KeyspaceMetadata ks, Session session, String cfName,
36 - String[] columns, String dumpPrefix) throws Exception { 36 + String[] columns, String[] defaultValues, String dumpPrefix) throws Exception {
37 if (ks.getTable(cfName) != null) { 37 if (ks.getTable(cfName) != null) {
38 Path dumpFile = Files.createTempFile(dumpPrefix, null); 38 Path dumpFile = Files.createTempFile(dumpPrefix, null);
39 Files.deleteIfExists(dumpFile); 39 Files.deleteIfExists(dumpFile);
@@ -45,7 +45,7 @@ public class CassandraDbHelper { @@ -45,7 +45,7 @@ public class CassandraDbHelper {
45 while (iter.hasNext()) { 45 while (iter.hasNext()) {
46 Row row = iter.next(); 46 Row row = iter.next();
47 if (row != null) { 47 if (row != null) {
48 - dumpRow(row, columns, csvPrinter); 48 + dumpRow(row, columns, defaultValues, csvPrinter);
49 } 49 }
50 } 50 }
51 } 51 }
@@ -89,18 +89,25 @@ public class CassandraDbHelper { @@ -89,18 +89,25 @@ public class CassandraDbHelper {
89 } 89 }
90 90
91 91
92 - private static void dumpRow(Row row, String[] columns, CSVPrinter csvPrinter) throws Exception { 92 + private static void dumpRow(Row row, String[] columns, String[] defaultValues, CSVPrinter csvPrinter) throws Exception {
93 List<String> record = new ArrayList<>(); 93 List<String> record = new ArrayList<>();
94 - for (String column : columns) {  
95 - record.add(getColumnValue(column, row)); 94 + for (int i=0;i<columns.length;i++) {
  95 + String column = columns[i];
  96 + String defaultValue;
  97 + if (defaultValues != null && i < defaultValues.length) {
  98 + defaultValue = defaultValues[i];
  99 + } else {
  100 + defaultValue = "";
  101 + }
  102 + record.add(getColumnValue(column, defaultValue, row));
96 } 103 }
97 csvPrinter.printRecord(record); 104 csvPrinter.printRecord(record);
98 } 105 }
99 106
100 - private static String getColumnValue(String column, Row row) {  
101 - String str = ""; 107 + private static String getColumnValue(String column, String defaultValue, Row row) {
102 int index = row.getColumnDefinitions().getIndexOf(column); 108 int index = row.getColumnDefinitions().getIndexOf(column);
103 if (index > -1) { 109 if (index > -1) {
  110 + String str;
104 DataType type = row.getColumnDefinitions().getType(index); 111 DataType type = row.getColumnDefinitions().getType(index);
105 try { 112 try {
106 if (row.isNull(index)) { 113 if (row.isNull(index)) {
@@ -123,8 +130,10 @@ public class CassandraDbHelper { @@ -123,8 +130,10 @@ public class CassandraDbHelper {
123 } catch (Exception e) { 130 } catch (Exception e) {
124 str = ""; 131 str = "";
125 } 132 }
  133 + return str;
  134 + } else {
  135 + return defaultValue;
126 } 136 }
127 - return str;  
128 } 137 }
129 138
130 private static String createInsertStatement(String cfName, String[] columns) { 139 private static String createInsertStatement(String cfName, String[] columns) {
@@ -15,30 +15,31 @@ @@ -15,30 +15,31 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
18 -import static org.hamcrest.Matchers.containsString;  
19 -import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;  
20 -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;  
21 -  
22 -import java.util.ArrayList;  
23 -import java.util.Collections;  
24 -import java.util.List;  
25 - 18 +import com.datastax.driver.core.utils.UUIDs;
  19 +import com.fasterxml.jackson.core.type.TypeReference;
26 import org.apache.commons.lang3.RandomStringUtils; 20 import org.apache.commons.lang3.RandomStringUtils;
27 -import org.thingsboard.server.common.data.*; 21 +import org.junit.After;
  22 +import org.junit.Assert;
  23 +import org.junit.Before;
  24 +import org.junit.Test;
  25 +import org.thingsboard.server.common.data.Customer;
  26 +import org.thingsboard.server.common.data.EntitySubtype;
  27 +import org.thingsboard.server.common.data.Tenant;
  28 +import org.thingsboard.server.common.data.User;
28 import org.thingsboard.server.common.data.asset.Asset; 29 import org.thingsboard.server.common.data.asset.Asset;
29 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
30 import org.thingsboard.server.common.data.id.CustomerId; 30 import org.thingsboard.server.common.data.id.CustomerId;
31 import org.thingsboard.server.common.data.page.TextPageData; 31 import org.thingsboard.server.common.data.page.TextPageData;
32 import org.thingsboard.server.common.data.page.TextPageLink; 32 import org.thingsboard.server.common.data.page.TextPageLink;
33 import org.thingsboard.server.common.data.security.Authority; 33 import org.thingsboard.server.common.data.security.Authority;
34 import org.thingsboard.server.dao.model.ModelConstants; 34 import org.thingsboard.server.dao.model.ModelConstants;
35 -import org.junit.After;  
36 -import org.junit.Assert;  
37 -import org.junit.Before;  
38 -import org.junit.Test;  
39 35
40 -import com.datastax.driver.core.utils.UUIDs;  
41 -import com.fasterxml.jackson.core.type.TypeReference; 36 +import java.util.ArrayList;
  37 +import java.util.Collections;
  38 +import java.util.List;
  39 +
  40 +import static org.hamcrest.Matchers.containsString;
  41 +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  42 +import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
42 43
43 public abstract class BaseAssetControllerTest extends AbstractControllerTest { 44 public abstract class BaseAssetControllerTest extends AbstractControllerTest {
44 45
@@ -128,8 +129,8 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest { @@ -128,8 +129,8 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest {
128 asset.setType("typeA"); 129 asset.setType("typeA");
129 assets.add(doPost("/api/asset", asset, Asset.class)); 130 assets.add(doPost("/api/asset", asset, Asset.class));
130 } 131 }
131 - List<TenantAssetType> assetTypes = doGetTyped("/api/asset/types",  
132 - new TypeReference<List<TenantAssetType>>(){}); 132 + List<EntitySubtype> assetTypes = doGetTyped("/api/asset/types",
  133 + new TypeReference<List<EntitySubtype>>(){});
133 134
134 Assert.assertNotNull(assetTypes); 135 Assert.assertNotNull(assetTypes);
135 Assert.assertEquals(3, assetTypes.size()); 136 Assert.assertEquals(3, assetTypes.size());
@@ -140,8 +140,8 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest { @@ -140,8 +140,8 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest {
140 device.setType("typeA"); 140 device.setType("typeA");
141 devices.add(doPost("/api/device", device, Device.class)); 141 devices.add(doPost("/api/device", device, Device.class));
142 } 142 }
143 - List<TenantDeviceType> deviceTypes = doGetTyped("/api/device/types",  
144 - new TypeReference<List<TenantDeviceType>>(){}); 143 + List<EntitySubtype> deviceTypes = doGetTyped("/api/device/types",
  144 + new TypeReference<List<EntitySubtype>>(){});
145 145
146 Assert.assertNotNull(deviceTypes); 146 Assert.assertNotNull(deviceTypes);
147 Assert.assertEquals(3, deviceTypes.size()); 147 Assert.assertEquals(3, deviceTypes.size());
common/data/src/main/java/org/thingsboard/server/common/data/EntitySubtype.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/TenantDeviceType.java
@@ -17,27 +17,21 @@ package org.thingsboard.server.common.data; @@ -17,27 +17,21 @@ package org.thingsboard.server.common.data;
17 17
18 import org.thingsboard.server.common.data.id.TenantId; 18 import org.thingsboard.server.common.data.id.TenantId;
19 19
20 -public class TenantDeviceType { 20 +public class EntitySubtype {
21 21
22 - private static final long serialVersionUID = 8057240243859922101L; 22 + private static final long serialVersionUID = 8057240243059922101L;
23 23
24 - private String type;  
25 private TenantId tenantId; 24 private TenantId tenantId;
  25 + private EntityType entityType;
  26 + private String type;
26 27
27 - public TenantDeviceType() { 28 + public EntitySubtype() {
28 super(); 29 super();
29 } 30 }
30 31
31 - public TenantDeviceType(String type, TenantId tenantId) {  
32 - this.type = type; 32 + public EntitySubtype(TenantId tenantId, EntityType entityType, String type) {
33 this.tenantId = tenantId; 33 this.tenantId = tenantId;
34 - }  
35 -  
36 - public String getType() {  
37 - return type;  
38 - }  
39 -  
40 - public void setType(String type) { 34 + this.entityType = entityType;
41 this.type = type; 35 this.type = type;
42 } 36 }
43 37
@@ -49,31 +43,52 @@ public class TenantDeviceType { @@ -49,31 +43,52 @@ public class TenantDeviceType {
49 this.tenantId = tenantId; 43 this.tenantId = tenantId;
50 } 44 }
51 45
52 - @Override  
53 - public int hashCode() {  
54 - int result = type != null ? type.hashCode() : 0;  
55 - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);  
56 - return result; 46 + public EntityType getEntityType() {
  47 + return entityType;
  48 + }
  49 +
  50 + public void setEntityType(EntityType entityType) {
  51 + this.entityType = entityType;
57 } 52 }
58 53
  54 + public String getType() {
  55 + return type;
  56 + }
  57 +
  58 + public void setType(String type) {
  59 + this.type = type;
  60 + }
  61 +
  62 +
59 @Override 63 @Override
60 public boolean equals(Object o) { 64 public boolean equals(Object o) {
61 if (this == o) return true; 65 if (this == o) return true;
62 if (o == null || getClass() != o.getClass()) return false; 66 if (o == null || getClass() != o.getClass()) return false;
63 67
64 - TenantDeviceType that = (TenantDeviceType) o; 68 + EntitySubtype that = (EntitySubtype) o;
65 69
66 - if (type != null ? !type.equals(that.type) : that.type != null) return false;  
67 - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null; 70 + if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false;
  71 + if (entityType != that.entityType) return false;
  72 + return type != null ? type.equals(that.type) : that.type == null;
68 73
69 } 74 }
70 75
71 @Override 76 @Override
  77 + public int hashCode() {
  78 + int result = tenantId != null ? tenantId.hashCode() : 0;
  79 + result = 31 * result + (entityType != null ? entityType.hashCode() : 0);
  80 + result = 31 * result + (type != null ? type.hashCode() : 0);
  81 + return result;
  82 + }
  83 +
  84 + @Override
72 public String toString() { 85 public String toString() {
73 - final StringBuilder sb = new StringBuilder("TenantDeviceType{");  
74 - sb.append("type='").append(type).append('\'');  
75 - sb.append(", tenantId=").append(tenantId); 86 + final StringBuilder sb = new StringBuilder("EntitySubtype{");
  87 + sb.append("tenantId=").append(tenantId);
  88 + sb.append(", entityType=").append(entityType);
  89 + sb.append(", type='").append(type).append('\'');
76 sb.append('}'); 90 sb.append('}');
77 return sb.toString(); 91 return sb.toString();
78 } 92 }
  93 +
79 } 94 }
1 -/**  
2 - * Copyright © 2016-2017 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.common.data.asset;  
17 -  
18 -import org.thingsboard.server.common.data.UUIDConverter;  
19 -import org.thingsboard.server.common.data.id.TenantId;  
20 -  
21 -import java.util.UUID;  
22 -  
23 -public class TenantAssetType {  
24 -  
25 - private static final long serialVersionUID = 8057290243855622101L;  
26 -  
27 - private String type;  
28 - private TenantId tenantId;  
29 -  
30 - public TenantAssetType() {  
31 - super();  
32 - }  
33 -  
34 - public TenantAssetType(String type, TenantId tenantId) {  
35 - this.type = type;  
36 - this.tenantId = tenantId;  
37 - }  
38 -  
39 - public TenantAssetType(String type, UUID tenantId) {  
40 - this.type = type;  
41 - this.tenantId = new TenantId(tenantId);  
42 - }  
43 -  
44 - public TenantAssetType(String type, String tenantId) {  
45 - this.type = type;  
46 - this.tenantId = new TenantId(UUIDConverter.fromString(tenantId));  
47 - }  
48 -  
49 - public String getType() {  
50 - return type;  
51 - }  
52 -  
53 - public void setType(String type) {  
54 - this.type = type;  
55 - }  
56 -  
57 - public TenantId getTenantId() {  
58 - return tenantId;  
59 - }  
60 -  
61 - public void setTenantId(TenantId tenantId) {  
62 - this.tenantId = tenantId;  
63 - }  
64 -  
65 - @Override  
66 - public int hashCode() {  
67 - int result = type != null ? type.hashCode() : 0;  
68 - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);  
69 - return result;  
70 - }  
71 -  
72 - @Override  
73 - public boolean equals(Object o) {  
74 - if (this == o) return true;  
75 - if (o == null || getClass() != o.getClass()) return false;  
76 -  
77 - TenantAssetType that = (TenantAssetType) o;  
78 -  
79 - if (type != null ? !type.equals(that.type) : that.type != null) return false;  
80 - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;  
81 -  
82 - }  
83 -  
84 - @Override  
85 - public String toString() {  
86 - final StringBuilder sb = new StringBuilder("TenantAssetType{");  
87 - sb.append("type='").append(type).append('\'');  
88 - sb.append(", tenantId=").append(tenantId);  
89 - sb.append('}');  
90 - return sb.toString();  
91 - }  
92 -}  
@@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
16 package org.thingsboard.server.dao.asset; 16 package org.thingsboard.server.dao.asset;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.EntitySubtype;
19 import org.thingsboard.server.common.data.asset.Asset; 20 import org.thingsboard.server.common.data.asset.Asset;
20 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
21 import org.thingsboard.server.common.data.page.TextPageLink; 21 import org.thingsboard.server.common.data.page.TextPageLink;
22 import org.thingsboard.server.dao.Dao; 22 import org.thingsboard.server.dao.Dao;
23 23
@@ -112,6 +112,6 @@ public interface AssetDao extends Dao<Asset> { @@ -112,6 +112,6 @@ public interface AssetDao extends Dao<Asset> {
112 * 112 *
113 * @return the list of tenant asset type objects 113 * @return the list of tenant asset type objects
114 */ 114 */
115 - ListenableFuture<List<TenantAssetType>> findTenantAssetTypesAsync(); 115 + ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId);
116 116
117 } 117 }
@@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
16 package org.thingsboard.server.dao.asset; 16 package org.thingsboard.server.dao.asset;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.EntitySubtype;
19 import org.thingsboard.server.common.data.asset.Asset; 20 import org.thingsboard.server.common.data.asset.Asset;
20 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
21 import org.thingsboard.server.common.data.id.AssetId; 21 import org.thingsboard.server.common.data.id.AssetId;
22 import org.thingsboard.server.common.data.id.CustomerId; 22 import org.thingsboard.server.common.data.id.CustomerId;
23 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
@@ -61,5 +61,5 @@ public interface AssetService { @@ -61,5 +61,5 @@ public interface AssetService {
61 61
62 ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query); 62 ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query);
63 63
64 - ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId); 64 + ListenableFuture<List<EntitySubtype>> findAssetTypesByTenantId(TenantId tenantId);
65 } 65 }
@@ -25,10 +25,10 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -25,10 +25,10 @@ import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.stereotype.Service; 25 import org.springframework.stereotype.Service;
26 import org.springframework.util.StringUtils; 26 import org.springframework.util.StringUtils;
27 import org.thingsboard.server.common.data.Customer; 27 import org.thingsboard.server.common.data.Customer;
  28 +import org.thingsboard.server.common.data.EntitySubtype;
28 import org.thingsboard.server.common.data.EntityType; 29 import org.thingsboard.server.common.data.EntityType;
29 import org.thingsboard.server.common.data.Tenant; 30 import org.thingsboard.server.common.data.Tenant;
30 import org.thingsboard.server.common.data.asset.Asset; 31 import org.thingsboard.server.common.data.asset.Asset;
31 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
32 import org.thingsboard.server.common.data.id.AssetId; 32 import org.thingsboard.server.common.data.id.AssetId;
33 import org.thingsboard.server.common.data.id.CustomerId; 33 import org.thingsboard.server.common.data.id.CustomerId;
34 import org.thingsboard.server.common.data.id.EntityId; 34 import org.thingsboard.server.common.data.id.EntityId;
@@ -217,22 +217,15 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ @@ -217,22 +217,15 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
217 } 217 }
218 218
219 @Override 219 @Override
220 - public ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId) { 220 + public ListenableFuture<List<EntitySubtype>> findAssetTypesByTenantId(TenantId tenantId) {
221 log.trace("Executing findAssetTypesByTenantId, tenantId [{}]", tenantId); 221 log.trace("Executing findAssetTypesByTenantId, tenantId [{}]", tenantId);
222 validateId(tenantId, "Incorrect tenantId " + tenantId); 222 validateId(tenantId, "Incorrect tenantId " + tenantId);
223 - ListenableFuture<List<TenantAssetType>> tenantAssetTypeEntities = assetDao.findTenantAssetTypesAsync();  
224 - ListenableFuture<List<TenantAssetType>> tenantAssetTypes = Futures.transform(tenantAssetTypeEntities,  
225 - (Function<List<TenantAssetType>, List<TenantAssetType>>) assetTypeEntities -> {  
226 - List<TenantAssetType> assetTypes = new ArrayList<>();  
227 - for (TenantAssetType assetType : assetTypeEntities) {  
228 - if (assetType.getTenantId().equals(tenantId)) {  
229 - assetTypes.add(assetType);  
230 - }  
231 - }  
232 - assetTypes.sort(Comparator.comparing(TenantAssetType::getType)); 223 + ListenableFuture<List<EntitySubtype>> tenantAssetTypes = assetDao.findTenantAssetTypesAsync(tenantId.getId());
  224 + return Futures.transform(tenantAssetTypes,
  225 + (Function<List<EntitySubtype>, List<EntitySubtype>>) assetTypes -> {
  226 + assetTypes.sort(Comparator.comparing(EntitySubtype::getType));
233 return assetTypes; 227 return assetTypes;
234 }); 228 });
235 - return tenantAssetTypes;  
236 } 229 }
237 230
238 private DataValidator<Asset> assetValidator = 231 private DataValidator<Asset> assetValidator =
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset; @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset;
17 17
18 import com.datastax.driver.core.ResultSet; 18 import com.datastax.driver.core.ResultSet;
19 import com.datastax.driver.core.ResultSetFuture; 19 import com.datastax.driver.core.ResultSetFuture;
  20 +import com.datastax.driver.core.Statement;
20 import com.datastax.driver.core.querybuilder.Select; 21 import com.datastax.driver.core.querybuilder.Select;
21 import com.datastax.driver.mapping.Result; 22 import com.datastax.driver.mapping.Result;
22 import com.google.common.base.Function; 23 import com.google.common.base.Function;
@@ -24,11 +25,12 @@ import com.google.common.util.concurrent.Futures; @@ -24,11 +25,12 @@ import com.google.common.util.concurrent.Futures;
24 import com.google.common.util.concurrent.ListenableFuture; 25 import com.google.common.util.concurrent.ListenableFuture;
25 import lombok.extern.slf4j.Slf4j; 26 import lombok.extern.slf4j.Slf4j;
26 import org.springframework.stereotype.Component; 27 import org.springframework.stereotype.Component;
  28 +import org.thingsboard.server.common.data.EntitySubtype;
  29 +import org.thingsboard.server.common.data.EntityType;
27 import org.thingsboard.server.common.data.asset.Asset; 30 import org.thingsboard.server.common.data.asset.Asset;
28 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
29 import org.thingsboard.server.common.data.page.TextPageLink; 31 import org.thingsboard.server.common.data.page.TextPageLink;
30 import org.thingsboard.server.dao.DaoUtil; 32 import org.thingsboard.server.dao.DaoUtil;
31 -import org.thingsboard.server.dao.model.TenantAssetTypeEntity; 33 +import org.thingsboard.server.dao.model.EntitySubtypeEntity;
32 import org.thingsboard.server.dao.model.nosql.AssetEntity; 34 import org.thingsboard.server.dao.model.nosql.AssetEntity;
33 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; 35 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
34 import org.thingsboard.server.dao.util.NoSqlDao; 36 import org.thingsboard.server.dao.util.NoSqlDao;
@@ -55,6 +57,16 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit @@ -55,6 +57,16 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
55 } 57 }
56 58
57 @Override 59 @Override
  60 + public Asset save(Asset domain) {
  61 + Asset savedAsset = super.save(domain);
  62 + EntitySubtype entitySubtype = new EntitySubtype(savedAsset.getTenantId(), EntityType.ASSET, savedAsset.getType());
  63 + EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
  64 + Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
  65 + executeWrite(saveStatement);
  66 + return savedAsset;
  67 + }
  68 +
  69 + @Override
58 public List<Asset> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink) { 70 public List<Asset> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink) {
59 log.debug("Try to find assets by tenantId [{}] and pageLink [{}]", tenantId, pageLink); 71 log.debug("Try to find assets by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
60 List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, 72 List<AssetEntity> assetEntities = findPageWithTextSearch(ASSET_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
@@ -130,36 +142,29 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit @@ -130,36 +142,29 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
130 } 142 }
131 143
132 @Override 144 @Override
133 - public ListenableFuture<List<TenantAssetType>> findTenantAssetTypesAsync() {  
134 - Select statement = select().distinct().column(ASSET_TYPE_PROPERTY).column(ASSET_TENANT_ID_PROPERTY).from(ASSET_TYPES_BY_TENANT_VIEW_NAME);  
135 - statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());  
136 - ResultSetFuture resultSetFuture = getSession().executeAsync(statement);  
137 - ListenableFuture<List<TenantAssetTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantAssetTypeEntity>>() { 145 + public ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId) {
  146 + Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME);
  147 + Select.Where query = select.where();
  148 + query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
  149 + query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.ASSET));
  150 + query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
  151 + ResultSetFuture resultSetFuture = getSession().executeAsync(query);
  152 + return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
138 @Nullable 153 @Nullable
139 @Override 154 @Override
140 - public List<TenantAssetTypeEntity> apply(@Nullable ResultSet resultSet) {  
141 - Result<TenantAssetTypeEntity> result = cluster.getMapper(TenantAssetTypeEntity.class).map(resultSet); 155 + public List<EntitySubtype> apply(@Nullable ResultSet resultSet) {
  156 + Result<EntitySubtypeEntity> result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet);
142 if (result != null) { 157 if (result != null) {
143 - return result.all(); 158 + List<EntitySubtype> entitySubtypes = new ArrayList<>();
  159 + result.all().forEach((entitySubtypeEntity) ->
  160 + entitySubtypes.add(entitySubtypeEntity.toEntitySubtype())
  161 + );
  162 + return entitySubtypes;
144 } else { 163 } else {
145 return Collections.emptyList(); 164 return Collections.emptyList();
146 } 165 }
147 } 166 }
148 }); 167 });
149 - return Futures.transform(result, new Function<List<TenantAssetTypeEntity>, List<TenantAssetType>>() {  
150 - @Nullable  
151 - @Override  
152 - public List<TenantAssetType> apply(@Nullable List<TenantAssetTypeEntity> entityList) {  
153 - List<TenantAssetType> list = Collections.emptyList();  
154 - if (entityList != null && !entityList.isEmpty()) {  
155 - list = new ArrayList<>();  
156 - for (TenantAssetTypeEntity object : entityList) {  
157 - list.add(object.toTenantAssetType());  
158 - }  
159 - }  
160 - return list;  
161 - }  
162 - });  
163 } 168 }
164 169
165 } 170 }
@@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device; @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device;
17 17
18 import com.datastax.driver.core.ResultSet; 18 import com.datastax.driver.core.ResultSet;
19 import com.datastax.driver.core.ResultSetFuture; 19 import com.datastax.driver.core.ResultSetFuture;
  20 +import com.datastax.driver.core.Statement;
20 import com.datastax.driver.core.querybuilder.Select; 21 import com.datastax.driver.core.querybuilder.Select;
21 import com.datastax.driver.mapping.Result; 22 import com.datastax.driver.mapping.Result;
22 import com.google.common.base.Function; 23 import com.google.common.base.Function;
@@ -25,10 +26,11 @@ import com.google.common.util.concurrent.ListenableFuture; @@ -25,10 +26,11 @@ import com.google.common.util.concurrent.ListenableFuture;
25 import lombok.extern.slf4j.Slf4j; 26 import lombok.extern.slf4j.Slf4j;
26 import org.springframework.stereotype.Component; 27 import org.springframework.stereotype.Component;
27 import org.thingsboard.server.common.data.Device; 28 import org.thingsboard.server.common.data.Device;
28 -import org.thingsboard.server.common.data.TenantDeviceType; 29 +import org.thingsboard.server.common.data.EntitySubtype;
  30 +import org.thingsboard.server.common.data.EntityType;
29 import org.thingsboard.server.common.data.page.TextPageLink; 31 import org.thingsboard.server.common.data.page.TextPageLink;
30 import org.thingsboard.server.dao.DaoUtil; 32 import org.thingsboard.server.dao.DaoUtil;
31 -import org.thingsboard.server.dao.model.TenantDeviceTypeEntity; 33 +import org.thingsboard.server.dao.model.EntitySubtypeEntity;
32 import org.thingsboard.server.dao.model.nosql.DeviceEntity; 34 import org.thingsboard.server.dao.model.nosql.DeviceEntity;
33 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao; 35 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
34 import org.thingsboard.server.dao.util.NoSqlDao; 36 import org.thingsboard.server.dao.util.NoSqlDao;
@@ -55,6 +57,16 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt @@ -55,6 +57,16 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
55 } 57 }
56 58
57 @Override 59 @Override
  60 + public Device save(Device domain) {
  61 + Device savedDevice = super.save(domain);
  62 + EntitySubtype entitySubtype = new EntitySubtype(savedDevice.getTenantId(), EntityType.DEVICE, savedDevice.getType());
  63 + EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
  64 + Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
  65 + executeWrite(saveStatement);
  66 + return savedDevice;
  67 + }
  68 +
  69 + @Override
58 public List<Device> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink) { 70 public List<Device> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink) {
59 log.debug("Try to find devices by tenantId [{}] and pageLink [{}]", tenantId, pageLink); 71 log.debug("Try to find devices by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
60 List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, 72 List<DeviceEntity> deviceEntities = findPageWithTextSearch(DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME,
@@ -130,36 +142,29 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt @@ -130,36 +142,29 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
130 } 142 }
131 143
132 @Override 144 @Override
133 - public ListenableFuture<List<TenantDeviceType>> findTenantDeviceTypesAsync() {  
134 - Select statement = select().distinct().column(DEVICE_TYPE_PROPERTY).column(DEVICE_TENANT_ID_PROPERTY).from(DEVICE_TYPES_BY_TENANT_VIEW_NAME);  
135 - statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());  
136 - ResultSetFuture resultSetFuture = getSession().executeAsync(statement);  
137 - ListenableFuture<List<TenantDeviceTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantDeviceTypeEntity>>() { 145 + public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) {
  146 + Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME);
  147 + Select.Where query = select.where();
  148 + query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
  149 + query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.DEVICE));
  150 + query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
  151 + ResultSetFuture resultSetFuture = getSession().executeAsync(query);
  152 + return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
138 @Nullable 153 @Nullable
139 @Override 154 @Override
140 - public List<TenantDeviceTypeEntity> apply(@Nullable ResultSet resultSet) {  
141 - Result<TenantDeviceTypeEntity> result = cluster.getMapper(TenantDeviceTypeEntity.class).map(resultSet); 155 + public List<EntitySubtype> apply(@Nullable ResultSet resultSet) {
  156 + Result<EntitySubtypeEntity> result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet);
142 if (result != null) { 157 if (result != null) {
143 - return result.all(); 158 + List<EntitySubtype> entitySubtypes = new ArrayList<>();
  159 + result.all().forEach((entitySubtypeEntity) ->
  160 + entitySubtypes.add(entitySubtypeEntity.toEntitySubtype())
  161 + );
  162 + return entitySubtypes;
144 } else { 163 } else {
145 return Collections.emptyList(); 164 return Collections.emptyList();
146 } 165 }
147 } 166 }
148 }); 167 });
149 - return Futures.transform(result, new Function<List<TenantDeviceTypeEntity>, List<TenantDeviceType>>() {  
150 - @Nullable  
151 - @Override  
152 - public List<TenantDeviceType> apply(@Nullable List<TenantDeviceTypeEntity> entityList) {  
153 - List<TenantDeviceType> list = Collections.emptyList();  
154 - if (entityList != null && !entityList.isEmpty()) {  
155 - list = new ArrayList<>();  
156 - for (TenantDeviceTypeEntity object : entityList) {  
157 - list.add(object.toTenantDeviceType());  
158 - }  
159 - }  
160 - return list;  
161 - }  
162 - });  
163 } 168 }
164 169
165 } 170 }
@@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device; @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.Device; 19 import org.thingsboard.server.common.data.Device;
20 -import org.thingsboard.server.common.data.TenantDeviceType; 20 +import org.thingsboard.server.common.data.EntitySubtype;
21 import org.thingsboard.server.common.data.page.TextPageLink; 21 import org.thingsboard.server.common.data.page.TextPageLink;
22 import org.thingsboard.server.dao.Dao; 22 import org.thingsboard.server.dao.Dao;
23 23
@@ -113,5 +113,5 @@ public interface DeviceDao extends Dao<Device> { @@ -113,5 +113,5 @@ public interface DeviceDao extends Dao<Device> {
113 * 113 *
114 * @return the list of tenant device type objects 114 * @return the list of tenant device type objects
115 */ 115 */
116 - ListenableFuture<List<TenantDeviceType>> findTenantDeviceTypesAsync(); 116 + ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId);
117 } 117 }
@@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device; @@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device;
17 17
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.Device; 19 import org.thingsboard.server.common.data.Device;
20 -import org.thingsboard.server.common.data.TenantDeviceType; 20 +import org.thingsboard.server.common.data.EntitySubtype;
21 import org.thingsboard.server.common.data.id.CustomerId; 21 import org.thingsboard.server.common.data.id.CustomerId;
22 import org.thingsboard.server.common.data.id.DeviceId; 22 import org.thingsboard.server.common.data.id.DeviceId;
23 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
@@ -61,6 +61,6 @@ public interface DeviceService { @@ -61,6 +61,6 @@ public interface DeviceService {
61 61
62 ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query); 62 ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query);
63 63
64 - ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId); 64 + ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId);
65 65
66 } 66 }
@@ -237,22 +237,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe @@ -237,22 +237,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
237 } 237 }
238 238
239 @Override 239 @Override
240 - public ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId) { 240 + public ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId) {
241 log.trace("Executing findDeviceTypesByTenantId, tenantId [{}]", tenantId); 241 log.trace("Executing findDeviceTypesByTenantId, tenantId [{}]", tenantId);
242 validateId(tenantId, "Incorrect tenantId " + tenantId); 242 validateId(tenantId, "Incorrect tenantId " + tenantId);
243 - ListenableFuture<List<TenantDeviceType>> tenantDeviceTypeEntities = deviceDao.findTenantDeviceTypesAsync();  
244 - ListenableFuture<List<TenantDeviceType>> tenantDeviceTypes = Futures.transform(tenantDeviceTypeEntities,  
245 - (Function<List<TenantDeviceType>, List<TenantDeviceType>>) deviceTypeEntities -> {  
246 - List<TenantDeviceType> deviceTypes = new ArrayList<>();  
247 - for (TenantDeviceType deviceType : deviceTypeEntities) {  
248 - if (deviceType.getTenantId().equals(tenantId)) {  
249 - deviceTypes.add(deviceType);  
250 - }  
251 - }  
252 - deviceTypes.sort(Comparator.comparing(TenantDeviceType::getType)); 243 + ListenableFuture<List<EntitySubtype>> tenantDeviceTypes = deviceDao.findTenantDeviceTypesAsync(tenantId.getId());
  244 + return Futures.transform(tenantDeviceTypes,
  245 + (Function<List<EntitySubtype>, List<EntitySubtype>>) deviceTypes -> {
  246 + deviceTypes.sort(Comparator.comparing(EntitySubtype::getType));
253 return deviceTypes; 247 return deviceTypes;
254 - });  
255 - return tenantDeviceTypes; 248 + });
256 } 249 }
257 250
258 private DataValidator<Device> deviceValidator = 251 private DataValidator<Device> deviceValidator =
dao/src/main/java/org/thingsboard/server/dao/model/EntitySubtypeEntity.java renamed from dao/src/main/java/org/thingsboard/server/dao/model/TenantAssetTypeEntity.java
@@ -20,44 +20,41 @@ import com.datastax.driver.mapping.annotations.Column; @@ -20,44 +20,41 @@ import com.datastax.driver.mapping.annotations.Column;
20 import com.datastax.driver.mapping.annotations.PartitionKey; 20 import com.datastax.driver.mapping.annotations.PartitionKey;
21 import com.datastax.driver.mapping.annotations.Table; 21 import com.datastax.driver.mapping.annotations.Table;
22 import com.datastax.driver.mapping.annotations.Transient; 22 import com.datastax.driver.mapping.annotations.Transient;
23 -import org.thingsboard.server.common.data.asset.TenantAssetType; 23 +import org.thingsboard.server.common.data.EntitySubtype;
  24 +import org.thingsboard.server.common.data.EntityType;
24 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
  26 +import org.thingsboard.server.dao.model.type.EntityTypeCodec;
25 27
26 import java.util.UUID; 28 import java.util.UUID;
27 29
28 import static org.thingsboard.server.dao.model.ModelConstants.*; 30 import static org.thingsboard.server.dao.model.ModelConstants.*;
29 31
30 -@Table(name = ASSET_TYPES_BY_TENANT_VIEW_NAME)  
31 -public class TenantAssetTypeEntity { 32 +@Table(name = ENTITY_SUBTYPE_COLUMN_FAMILY_NAME)
  33 +public class EntitySubtypeEntity {
32 34
33 @Transient 35 @Transient
34 - private static final long serialVersionUID = -1268181161886910152L; 36 + private static final long serialVersionUID = -1268181961886910152L;
35 37
36 @PartitionKey(value = 0) 38 @PartitionKey(value = 0)
37 - @Column(name = ASSET_TYPE_PROPERTY)  
38 - private String type;  
39 -  
40 - @PartitionKey(value = 1)  
41 - @Column(name = ASSET_TENANT_ID_PROPERTY) 39 + @Column(name = ENTITY_SUBTYPE_TENANT_ID_PROPERTY)
42 private UUID tenantId; 40 private UUID tenantId;
43 41
44 - public TenantAssetTypeEntity() {  
45 - super();  
46 - } 42 + @PartitionKey(value = 1)
  43 + @Column(name = ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, codec = EntityTypeCodec.class)
  44 + private EntityType entityType;
47 45
48 - public TenantAssetTypeEntity(TenantAssetType tenantAssetType) {  
49 - this.type = tenantAssetType.getType();  
50 - if (tenantAssetType.getTenantId() != null) {  
51 - this.tenantId = tenantAssetType.getTenantId().getId();  
52 - }  
53 - } 46 + @PartitionKey(value = 2)
  47 + @Column(name = ENTITY_SUBTYPE_TYPE_PROPERTY)
  48 + private String type;
54 49
55 - public String getType() {  
56 - return type; 50 + public EntitySubtypeEntity() {
  51 + super();
57 } 52 }
58 53
59 - public void setType(String type) {  
60 - this.type = type; 54 + public EntitySubtypeEntity(EntitySubtype entitySubtype) {
  55 + this.tenantId = entitySubtype.getTenantId().getId();
  56 + this.entityType = entitySubtype.getEntityType();
  57 + this.type = entitySubtype.getType();
61 } 58 }
62 59
63 public UUID getTenantId() { 60 public UUID getTenantId() {
@@ -68,40 +65,59 @@ public class TenantAssetTypeEntity { @@ -68,40 +65,59 @@ public class TenantAssetTypeEntity {
68 this.tenantId = tenantId; 65 this.tenantId = tenantId;
69 } 66 }
70 67
71 - @Override  
72 - public int hashCode() {  
73 - int result = type != null ? type.hashCode() : 0;  
74 - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);  
75 - return result; 68 + public EntityType getEntityType() {
  69 + return entityType;
76 } 70 }
77 71
  72 + public void setEntityType(EntityType entityType) {
  73 + this.entityType = entityType;
  74 + }
  75 +
  76 + public String getType() {
  77 + return type;
  78 + }
  79 +
  80 + public void setType(String type) {
  81 + this.type = type;
  82 + }
  83 +
  84 +
78 @Override 85 @Override
79 public boolean equals(Object o) { 86 public boolean equals(Object o) {
80 if (this == o) return true; 87 if (this == o) return true;
81 if (o == null || getClass() != o.getClass()) return false; 88 if (o == null || getClass() != o.getClass()) return false;
82 89
83 - TenantAssetTypeEntity that = (TenantAssetTypeEntity) o; 90 + EntitySubtypeEntity that = (EntitySubtypeEntity) o;
  91 +
  92 + if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false;
  93 + if (entityType != that.entityType) return false;
  94 + return type != null ? type.equals(that.type) : that.type == null;
84 95
85 - if (type != null ? !type.equals(that.type) : that.type != null) return false;  
86 - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null; 96 + }
87 97
  98 + @Override
  99 + public int hashCode() {
  100 + int result = tenantId != null ? tenantId.hashCode() : 0;
  101 + result = 31 * result + (entityType != null ? entityType.hashCode() : 0);
  102 + result = 31 * result + (type != null ? type.hashCode() : 0);
  103 + return result;
88 } 104 }
89 105
90 @Override 106 @Override
91 public String toString() { 107 public String toString() {
92 - final StringBuilder sb = new StringBuilder("TenantAssetTypeEntity{");  
93 - sb.append("type='").append(type).append('\'');  
94 - sb.append(", tenantId=").append(tenantId); 108 + final StringBuilder sb = new StringBuilder("EntitySubtypeEntity{");
  109 + sb.append("tenantId=").append(tenantId);
  110 + sb.append(", entityType=").append(entityType);
  111 + sb.append(", type='").append(type).append('\'');
95 sb.append('}'); 112 sb.append('}');
96 return sb.toString(); 113 return sb.toString();
97 } 114 }
98 115
99 - public TenantAssetType toTenantAssetType() {  
100 - TenantAssetType tenantAssetType = new TenantAssetType();  
101 - tenantAssetType.setType(type);  
102 - if (tenantId != null) {  
103 - tenantAssetType.setTenantId(new TenantId(tenantId));  
104 - }  
105 - return tenantAssetType; 116 + public EntitySubtype toEntitySubtype() {
  117 + EntitySubtype entitySubtype = new EntitySubtype();
  118 + entitySubtype.setTenantId(new TenantId(tenantId));
  119 + entitySubtype.setEntityType(entityType);
  120 + entitySubtype.setType(type);
  121 + return entitySubtype;
106 } 122 }
107 } 123 }
@@ -151,6 +151,14 @@ public class ModelConstants { @@ -151,6 +151,14 @@ public class ModelConstants {
151 public static final String ASSET_TYPES_BY_TENANT_VIEW_NAME = "asset_types_by_tenant"; 151 public static final String ASSET_TYPES_BY_TENANT_VIEW_NAME = "asset_types_by_tenant";
152 152
153 /** 153 /**
  154 + * Cassandra entity_subtype constants.
  155 + */
  156 + public static final String ENTITY_SUBTYPE_COLUMN_FAMILY_NAME = "entity_subtype";
  157 + public static final String ENTITY_SUBTYPE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
  158 + public static final String ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY = "entity_type";
  159 + public static final String ENTITY_SUBTYPE_TYPE_PROPERTY = "type";
  160 +
  161 + /**
154 * Cassandra alarm constants. 162 * Cassandra alarm constants.
155 */ 163 */
156 public static final String ALARM_COLUMN_FAMILY_NAME = "alarm"; 164 public static final String ALARM_COLUMN_FAMILY_NAME = "alarm";
1 -/**  
2 - * Copyright © 2016-2017 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -  
17 -package org.thingsboard.server.dao.model;  
18 -  
19 -import com.datastax.driver.mapping.annotations.Column;  
20 -import com.datastax.driver.mapping.annotations.PartitionKey;  
21 -import com.datastax.driver.mapping.annotations.Table;  
22 -import com.datastax.driver.mapping.annotations.Transient;  
23 -import org.thingsboard.server.common.data.TenantDeviceType;  
24 -import org.thingsboard.server.common.data.id.TenantId;  
25 -  
26 -import java.util.UUID;  
27 -  
28 -import static org.thingsboard.server.dao.model.ModelConstants.*;  
29 -  
30 -@Table(name = DEVICE_TYPES_BY_TENANT_VIEW_NAME)  
31 -public class TenantDeviceTypeEntity {  
32 -  
33 - @Transient  
34 - private static final long serialVersionUID = -1268181166886910152L;  
35 -  
36 - @PartitionKey(value = 0)  
37 - @Column(name = DEVICE_TYPE_PROPERTY)  
38 - private String type;  
39 -  
40 - @PartitionKey(value = 1)  
41 - @Column(name = DEVICE_TENANT_ID_PROPERTY)  
42 - private UUID tenantId;  
43 -  
44 - public TenantDeviceTypeEntity() {  
45 - super();  
46 - }  
47 -  
48 - public TenantDeviceTypeEntity(TenantDeviceType tenantDeviceType) {  
49 - this.type = tenantDeviceType.getType();  
50 - if (tenantDeviceType.getTenantId() != null) {  
51 - this.tenantId = tenantDeviceType.getTenantId().getId();  
52 - }  
53 - }  
54 -  
55 - public String getType() {  
56 - return type;  
57 - }  
58 -  
59 - public void setType(String type) {  
60 - this.type = type;  
61 - }  
62 -  
63 - public UUID getTenantId() {  
64 - return tenantId;  
65 - }  
66 -  
67 - public void setTenantId(UUID tenantId) {  
68 - this.tenantId = tenantId;  
69 - }  
70 -  
71 - @Override  
72 - public int hashCode() {  
73 - int result = type != null ? type.hashCode() : 0;  
74 - result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);  
75 - return result;  
76 - }  
77 -  
78 - @Override  
79 - public boolean equals(Object o) {  
80 - if (this == o) return true;  
81 - if (o == null || getClass() != o.getClass()) return false;  
82 -  
83 - TenantDeviceTypeEntity that = (TenantDeviceTypeEntity) o;  
84 -  
85 - if (type != null ? !type.equals(that.type) : that.type != null) return false;  
86 - return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;  
87 -  
88 - }  
89 -  
90 - @Override  
91 - public String toString() {  
92 - final StringBuilder sb = new StringBuilder("TenantDeviceTypeEntity{");  
93 - sb.append("type='").append(type).append('\'');  
94 - sb.append(", tenantId=").append(tenantId);  
95 - sb.append('}');  
96 - return sb.toString();  
97 - }  
98 -  
99 - public TenantDeviceType toTenantDeviceType() {  
100 - TenantDeviceType tenantDeviceType = new TenantDeviceType();  
101 - tenantDeviceType.setType(type);  
102 - if (tenantId != null) {  
103 - tenantDeviceType.setTenantId(new TenantId(tenantId));  
104 - }  
105 - return tenantDeviceType;  
106 - }  
107 -}  
1 -/**  
2 - * Copyright © 2016-2017 The Thingsboard Authors  
3 - *  
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at  
7 - *  
8 - * http://www.apache.org/licenses/LICENSE-2.0  
9 - *  
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and  
14 - * limitations under the License.  
15 - */  
16 -package org.thingsboard.server.dao.model.sql;  
17 -  
18 -import lombok.AllArgsConstructor;  
19 -import lombok.Data;  
20 -  
21 -@AllArgsConstructor  
22 -@Data  
23 -public class TenantDeviceTypeEntity {  
24 - private String tenantId;  
25 - private String type;  
26 -}  
@@ -19,7 +19,8 @@ import org.springframework.data.domain.Pageable; @@ -19,7 +19,8 @@ import org.springframework.data.domain.Pageable;
19 import org.springframework.data.jpa.repository.Query; 19 import org.springframework.data.jpa.repository.Query;
20 import org.springframework.data.repository.CrudRepository; 20 import org.springframework.data.repository.CrudRepository;
21 import org.springframework.data.repository.query.Param; 21 import org.springframework.data.repository.query.Param;
22 -import org.thingsboard.server.common.data.asset.TenantAssetType; 22 +import org.thingsboard.server.common.data.EntitySubtype;
  23 +import org.thingsboard.server.common.data.EntityType;
23 import org.thingsboard.server.dao.model.sql.AssetEntity; 24 import org.thingsboard.server.dao.model.sql.AssetEntity;
24 import org.thingsboard.server.dao.util.SqlDao; 25 import org.thingsboard.server.dao.util.SqlDao;
25 26
@@ -76,6 +77,7 @@ public interface AssetRepository extends CrudRepository<AssetEntity, String> { @@ -76,6 +77,7 @@ public interface AssetRepository extends CrudRepository<AssetEntity, String> {
76 @Param("idOffset") String idOffset, 77 @Param("idOffset") String idOffset,
77 Pageable pageable); 78 Pageable pageable);
78 79
79 - @Query("SELECT NEW org.thingsboard.server.common.data.asset.TenantAssetType(a.type, a.tenantId) FROM AssetEntity a GROUP BY a.tenantId, a.type")  
80 - List<TenantAssetType> findTenantAssetTypes(); 80 + @Query("SELECT DISTINCT a.type FROM AssetEntity a WHERE a.tenantId = :tenantId")
  81 + List<String> findTenantAssetTypes(@Param("tenantId") String tenantId);
  82 +
81 } 83 }
@@ -20,8 +20,10 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -20,8 +20,10 @@ import org.springframework.beans.factory.annotation.Autowired;
20 import org.springframework.data.domain.PageRequest; 20 import org.springframework.data.domain.PageRequest;
21 import org.springframework.data.repository.CrudRepository; 21 import org.springframework.data.repository.CrudRepository;
22 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
  23 +import org.thingsboard.server.common.data.EntitySubtype;
  24 +import org.thingsboard.server.common.data.EntityType;
23 import org.thingsboard.server.common.data.asset.Asset; 25 import org.thingsboard.server.common.data.asset.Asset;
24 -import org.thingsboard.server.common.data.asset.TenantAssetType; 26 +import org.thingsboard.server.common.data.id.TenantId;
25 import org.thingsboard.server.common.data.page.TextPageLink; 27 import org.thingsboard.server.common.data.page.TextPageLink;
26 import org.thingsboard.server.dao.DaoUtil; 28 import org.thingsboard.server.dao.DaoUtil;
27 import org.thingsboard.server.dao.asset.AssetDao; 29 import org.thingsboard.server.dao.asset.AssetDao;
@@ -29,10 +31,7 @@ import org.thingsboard.server.dao.model.sql.AssetEntity; @@ -29,10 +31,7 @@ import org.thingsboard.server.dao.model.sql.AssetEntity;
29 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; 31 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
30 import org.thingsboard.server.dao.util.SqlDao; 32 import org.thingsboard.server.dao.util.SqlDao;
31 33
32 -import java.util.List;  
33 -import java.util.Objects;  
34 -import java.util.Optional;  
35 -import java.util.UUID; 34 +import java.util.*;
36 35
37 import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; 36 import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
38 import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs; 37 import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs;
@@ -121,7 +120,18 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao<AssetEntity, Asset> im @@ -121,7 +120,18 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao<AssetEntity, Asset> im
121 } 120 }
122 121
123 @Override 122 @Override
124 - public ListenableFuture<List<TenantAssetType>> findTenantAssetTypesAsync() {  
125 - return service.submit(() -> assetRepository.findTenantAssetTypes()); 123 + public ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId) {
  124 + return service.submit(() -> convertTenantAssetTypesToDto(tenantId, assetRepository.findTenantAssetTypes(fromTimeUUID(tenantId))));
  125 + }
  126 +
  127 + private List<EntitySubtype> convertTenantAssetTypesToDto(UUID tenantId, List<String> types) {
  128 + List<EntitySubtype> list = Collections.emptyList();
  129 + if (types != null && !types.isEmpty()) {
  130 + list = new ArrayList<>();
  131 + for (String type : types) {
  132 + list.add(new EntitySubtype(new TenantId(tenantId), EntityType.ASSET, type));
  133 + }
  134 + }
  135 + return list;
126 } 136 }
127 } 137 }
@@ -20,7 +20,6 @@ import org.springframework.data.jpa.repository.Query; @@ -20,7 +20,6 @@ import org.springframework.data.jpa.repository.Query;
20 import org.springframework.data.repository.CrudRepository; 20 import org.springframework.data.repository.CrudRepository;
21 import org.springframework.data.repository.query.Param; 21 import org.springframework.data.repository.query.Param;
22 import org.thingsboard.server.dao.model.sql.DeviceEntity; 22 import org.thingsboard.server.dao.model.sql.DeviceEntity;
23 -import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity;  
24 import org.thingsboard.server.dao.util.SqlDao; 23 import org.thingsboard.server.dao.util.SqlDao;
25 24
26 import java.util.List; 25 import java.util.List;
@@ -72,8 +71,8 @@ public interface DeviceRepository extends CrudRepository<DeviceEntity, String> { @@ -72,8 +71,8 @@ public interface DeviceRepository extends CrudRepository<DeviceEntity, String> {
72 @Param("idOffset") String idOffset, 71 @Param("idOffset") String idOffset,
73 Pageable pageable); 72 Pageable pageable);
74 73
75 - @Query("SELECT DISTINCT NEW org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity(d.tenantId, d.type) FROM DeviceEntity d")  
76 - List<TenantDeviceTypeEntity> findTenantDeviceTypes(); 74 + @Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId")
  75 + List<String> findTenantDeviceTypes(@Param("tenantId") String tenantId);
77 76
78 DeviceEntity findByTenantIdAndName(String tenantId, String name); 77 DeviceEntity findByTenantIdAndName(String tenantId, String name);
79 78
@@ -21,14 +21,14 @@ import org.springframework.data.domain.PageRequest; @@ -21,14 +21,14 @@ import org.springframework.data.domain.PageRequest;
21 import org.springframework.data.repository.CrudRepository; 21 import org.springframework.data.repository.CrudRepository;
22 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
23 import org.thingsboard.server.common.data.Device; 23 import org.thingsboard.server.common.data.Device;
24 -import org.thingsboard.server.common.data.TenantDeviceType; 24 +import org.thingsboard.server.common.data.EntitySubtype;
  25 +import org.thingsboard.server.common.data.EntityType;
25 import org.thingsboard.server.common.data.UUIDConverter; 26 import org.thingsboard.server.common.data.UUIDConverter;
26 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
27 import org.thingsboard.server.common.data.page.TextPageLink; 28 import org.thingsboard.server.common.data.page.TextPageLink;
28 import org.thingsboard.server.dao.DaoUtil; 29 import org.thingsboard.server.dao.DaoUtil;
29 import org.thingsboard.server.dao.device.DeviceDao; 30 import org.thingsboard.server.dao.device.DeviceDao;
30 import org.thingsboard.server.dao.model.sql.DeviceEntity; 31 import org.thingsboard.server.dao.model.sql.DeviceEntity;
31 -import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity;  
32 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao; 32 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
33 import org.thingsboard.server.dao.util.SqlDao; 33 import org.thingsboard.server.dao.util.SqlDao;
34 34
@@ -120,16 +120,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device> @@ -120,16 +120,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
120 } 120 }
121 121
122 @Override 122 @Override
123 - public ListenableFuture<List<TenantDeviceType>> findTenantDeviceTypesAsync() {  
124 - return service.submit(() -> convertTenantDeviceTypeEntityToDto(deviceRepository.findTenantDeviceTypes())); 123 + public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) {
  124 + return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(fromTimeUUID(tenantId))));
125 } 125 }
126 126
127 - private List<TenantDeviceType> convertTenantDeviceTypeEntityToDto(List<TenantDeviceTypeEntity> entities) {  
128 - List<TenantDeviceType> list = Collections.emptyList();  
129 - if (entities != null && !entities.isEmpty()) { 127 + private List<EntitySubtype> convertTenantDeviceTypesToDto(UUID tenantId, List<String> types) {
  128 + List<EntitySubtype> list = Collections.emptyList();
  129 + if (types != null && !types.isEmpty()) {
130 list = new ArrayList<>(); 130 list = new ArrayList<>();
131 - for (TenantDeviceTypeEntity entity : entities) {  
132 - list.add(new TenantDeviceType(entity.getType(), new TenantId(UUIDConverter.fromString(entity.getTenantId())))); 131 + for (String type : types) {
  132 + list.add(new EntitySubtype(new TenantId(tenantId), EntityType.DEVICE, type));
133 } 133 }
134 } 134 }
135 return list; 135 return list;
@@ -197,13 +197,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an @@ -197,13 +197,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an
197 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) 197 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
198 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); 198 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
199 199
200 -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS  
201 - SELECT *  
202 - from thingsboard.device  
203 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL  
204 - PRIMARY KEY ( (type, tenant_id), id, customer_id)  
205 - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);  
206 -  
207 CREATE TABLE IF NOT EXISTS thingsboard.device_credentials ( 200 CREATE TABLE IF NOT EXISTS thingsboard.device_credentials (
208 id timeuuid PRIMARY KEY, 201 id timeuuid PRIMARY KEY,
209 device_id timeuuid, 202 device_id timeuuid,
@@ -270,12 +263,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and @@ -270,12 +263,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and
270 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id ) 263 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
271 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC ); 264 WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
272 265
273 -CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS  
274 - SELECT *  
275 - from thingsboard.asset  
276 - WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL  
277 - PRIMARY KEY ( (type, tenant_id), id, customer_id)  
278 - WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC); 266 +CREATE TABLE IF NOT EXISTS thingsboard.entity_subtype (
  267 + tenant_id timeuuid,
  268 + entity_type text, // (DEVICE, ASSET)
  269 + type text,
  270 + PRIMARY KEY (tenant_id, entity_type, type)
  271 +);
279 272
280 CREATE TABLE IF NOT EXISTS thingsboard.alarm ( 273 CREATE TABLE IF NOT EXISTS thingsboard.alarm (
281 id timeuuid, 274 id timeuuid,
@@ -22,9 +22,9 @@ import org.junit.Assert; @@ -22,9 +22,9 @@ import org.junit.Assert;
22 import org.junit.Before; 22 import org.junit.Before;
23 import org.junit.Test; 23 import org.junit.Test;
24 import org.thingsboard.server.common.data.Customer; 24 import org.thingsboard.server.common.data.Customer;
  25 +import org.thingsboard.server.common.data.EntitySubtype;
25 import org.thingsboard.server.common.data.Tenant; 26 import org.thingsboard.server.common.data.Tenant;
26 import org.thingsboard.server.common.data.asset.Asset; 27 import org.thingsboard.server.common.data.asset.Asset;
27 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
28 import org.thingsboard.server.common.data.id.CustomerId; 28 import org.thingsboard.server.common.data.id.CustomerId;
29 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
30 import org.thingsboard.server.common.data.page.TextPageData; 30 import org.thingsboard.server.common.data.page.TextPageData;
@@ -181,7 +181,7 @@ public abstract class BaseAssetServiceTest extends AbstractServiceTest { @@ -181,7 +181,7 @@ public abstract class BaseAssetServiceTest extends AbstractServiceTest {
181 asset.setType("typeA"); 181 asset.setType("typeA");
182 assets.add(assetService.saveAsset(asset)); 182 assets.add(assetService.saveAsset(asset));
183 } 183 }
184 - List<TenantAssetType> assetTypes = assetService.findAssetTypesByTenantId(tenantId).get(); 184 + List<EntitySubtype> assetTypes = assetService.findAssetTypesByTenantId(tenantId).get();
185 Assert.assertNotNull(assetTypes); 185 Assert.assertNotNull(assetTypes);
186 Assert.assertEquals(3, assetTypes.size()); 186 Assert.assertEquals(3, assetTypes.size());
187 Assert.assertEquals("typeA", assetTypes.get(0).getType()); 187 Assert.assertEquals("typeA", assetTypes.get(0).getType());
@@ -23,8 +23,8 @@ import org.junit.Before; @@ -23,8 +23,8 @@ import org.junit.Before;
23 import org.junit.Test; 23 import org.junit.Test;
24 import org.thingsboard.server.common.data.Customer; 24 import org.thingsboard.server.common.data.Customer;
25 import org.thingsboard.server.common.data.Device; 25 import org.thingsboard.server.common.data.Device;
  26 +import org.thingsboard.server.common.data.EntitySubtype;
26 import org.thingsboard.server.common.data.Tenant; 27 import org.thingsboard.server.common.data.Tenant;
27 -import org.thingsboard.server.common.data.TenantDeviceType;  
28 import org.thingsboard.server.common.data.id.CustomerId; 28 import org.thingsboard.server.common.data.id.CustomerId;
29 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
30 import org.thingsboard.server.common.data.page.TextPageData; 30 import org.thingsboard.server.common.data.page.TextPageData;
@@ -191,7 +191,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest { @@ -191,7 +191,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
191 device.setType("typeA"); 191 device.setType("typeA");
192 devices.add(deviceService.saveDevice(device)); 192 devices.add(deviceService.saveDevice(device));
193 } 193 }
194 - List<TenantDeviceType> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId).get(); 194 + List<EntitySubtype> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId).get();
195 Assert.assertNotNull(deviceTypes); 195 Assert.assertNotNull(deviceTypes);
196 Assert.assertEquals(3, deviceTypes.size()); 196 Assert.assertEquals(3, deviceTypes.size());
197 Assert.assertEquals("typeA", deviceTypes.get(0).getType()); 197 Assert.assertEquals("typeA", deviceTypes.get(0).getType());
@@ -19,8 +19,8 @@ import com.datastax.driver.core.utils.UUIDs; @@ -19,8 +19,8 @@ import com.datastax.driver.core.utils.UUIDs;
19 import com.google.common.util.concurrent.ListenableFuture; 19 import com.google.common.util.concurrent.ListenableFuture;
20 import org.junit.Test; 20 import org.junit.Test;
21 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.thingsboard.server.common.data.EntitySubtype;
22 import org.thingsboard.server.common.data.asset.Asset; 23 import org.thingsboard.server.common.data.asset.Asset;
23 -import org.thingsboard.server.common.data.asset.TenantAssetType;  
24 import org.thingsboard.server.common.data.id.AssetId; 24 import org.thingsboard.server.common.data.id.AssetId;
25 import org.thingsboard.server.common.data.id.CustomerId; 25 import org.thingsboard.server.common.data.id.CustomerId;
26 import org.thingsboard.server.common.data.id.TenantId; 26 import org.thingsboard.server.common.data.id.TenantId;
@@ -33,12 +33,9 @@ import java.util.List; @@ -33,12 +33,9 @@ import java.util.List;
33 import java.util.Optional; 33 import java.util.Optional;
34 import java.util.UUID; 34 import java.util.UUID;
35 import java.util.concurrent.ExecutionException; 35 import java.util.concurrent.ExecutionException;
36 -import java.util.stream.Collectors;  
37 36
38 import static junit.framework.TestCase.assertFalse; 37 import static junit.framework.TestCase.assertFalse;
39 -import static org.junit.Assert.assertEquals;  
40 -import static org.junit.Assert.assertNotNull;  
41 -import static org.junit.Assert.assertTrue; 38 +import static org.junit.Assert.*;
42 39
43 /** 40 /**
44 * Created by Valerii Sosliuk on 5/21/2017. 41 * Created by Valerii Sosliuk on 5/21/2017.
@@ -192,11 +189,10 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest { @@ -192,11 +189,10 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest {
192 saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_8", "TYPE_1"); 189 saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_8", "TYPE_1");
193 saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_9", "TYPE_1"); 190 saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_9", "TYPE_1");
194 191
195 - ListenableFuture<List<TenantAssetType>> tenantAssetTypesFuture = assetDao.findTenantAssetTypesAsync();  
196 - List<TenantAssetType> tenantAssetTypes = tenantAssetTypesFuture.get();  
197 - assertNotNull(tenantAssetTypes);  
198 - List<TenantAssetType> tenant1Types = tenantAssetTypes.stream().filter(t -> t.getTenantId().getId().equals(tenantId1)).collect(Collectors.toList());  
199 - List<TenantAssetType> tenant2Types = tenantAssetTypes.stream().filter(t -> t.getTenantId().getId().equals(tenantId2)).collect(Collectors.toList()); 192 + List<EntitySubtype> tenant1Types = assetDao.findTenantAssetTypesAsync(tenantId1).get();
  193 + assertNotNull(tenant1Types);
  194 + List<EntitySubtype> tenant2Types = assetDao.findTenantAssetTypesAsync(tenantId2).get();
  195 + assertNotNull(tenant2Types);
200 196
201 assertEquals(3, tenant1Types.size()); 197 assertEquals(3, tenant1Types.size());
202 assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_1"))); 198 assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_1")));