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 69 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
70 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 72 DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_name;
80 73 DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_search_text;
81 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 124 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
132 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 134 CREATE TABLE IF NOT EXISTS thingsboard.alarm (
142 135 id timeuuid,
... ...
... ... @@ -20,8 +20,8 @@ import org.springframework.http.HttpStatus;
20 20 import org.springframework.security.access.prepost.PreAuthorize;
21 21 import org.springframework.web.bind.annotation.*;
22 22 import org.thingsboard.server.common.data.Customer;
  23 +import org.thingsboard.server.common.data.EntitySubtype;
23 24 import org.thingsboard.server.common.data.asset.Asset;
24   -import org.thingsboard.server.common.data.asset.TenantAssetType;
25 25 import org.thingsboard.server.common.data.id.AssetId;
26 26 import org.thingsboard.server.common.data.id.CustomerId;
27 27 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -246,11 +246,11 @@ public class AssetController extends BaseController {
246 246 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
247 247 @RequestMapping(value = "/asset/types", method = RequestMethod.GET)
248 248 @ResponseBody
249   - public List<TenantAssetType> getAssetTypes() throws ThingsboardException {
  249 + public List<EntitySubtype> getAssetTypes() throws ThingsboardException {
250 250 try {
251 251 SecurityUser user = getCurrentUser();
252 252 TenantId tenantId = user.getTenantId();
253   - ListenableFuture<List<TenantAssetType>> assetTypes = assetService.findAssetTypesByTenantId(tenantId);
  253 + ListenableFuture<List<EntitySubtype>> assetTypes = assetService.findAssetTypesByTenantId(tenantId);
254 254 return checkNotNull(assetTypes.get());
255 255 } catch (Exception e) {
256 256 throw handleException(e);
... ...
... ... @@ -21,7 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
21 21 import org.springframework.web.bind.annotation.*;
22 22 import org.thingsboard.server.common.data.Customer;
23 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 25 import org.thingsboard.server.common.data.id.CustomerId;
26 26 import org.thingsboard.server.common.data.id.DeviceId;
27 27 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -283,11 +283,11 @@ public class DeviceController extends BaseController {
283 283 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
284 284 @RequestMapping(value = "/device/types", method = RequestMethod.GET)
285 285 @ResponseBody
286   - public List<TenantDeviceType> getDeviceTypes() throws ThingsboardException {
  286 + public List<EntitySubtype> getDeviceTypes() throws ThingsboardException {
287 287 try {
288 288 SecurityUser user = getCurrentUser();
289 289 TenantId tenantId = user.getTenantId();
290   - ListenableFuture<List<TenantDeviceType>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId);
  290 + ListenableFuture<List<EntitySubtype>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId);
291 291 return checkNotNull(deviceTypes.get());
292 292 } catch (Exception e) {
293 293 throw handleException(e);
... ...
... ... @@ -64,26 +64,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
64 64
65 65 log.info("Dumping devices ...");
66 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 69 "tb-devices");
69   - if (devicesDump != null) {
70   - CassandraDbHelper.appendToEndOfLine(devicesDump, "default");
71   - }
72 70 log.info("Devices dumped.");
73 71
74 72 log.info("Dumping assets ...");
75 73 Path assetsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset",
76 74 new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"},
  75 + new String[]{"", "", "", "", "", "", "default"},
77 76 "tb-assets");
78 77 log.info("Assets dumped.");
79 78
80 79 log.info("Dumping relations ...");
81 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 83 "tb-relations");
84   - if (relationsDump != null) {
85   - CassandraDbHelper.appendToEndOfLine(relationsDump, "COMMON");
86   - }
87 84 log.info("Relations dumped.");
88 85
89 86 log.info("Updating schema ...");
... ... @@ -101,6 +98,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
101 98 }
102 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 118 log.info("Restoring assets ...");
105 119 if (assetsDump != null) {
106 120 CassandraDbHelper.loadCf(ks, cluster.getSession(), "asset",
... ... @@ -109,6 +123,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
109 123 }
110 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 143 log.info("Restoring relations ...");
113 144 if (relationsDump != null) {
114 145 CassandraDbHelper.loadCf(ks, cluster.getSession(), "relation",
... ...
... ... @@ -33,7 +33,7 @@ public class CassandraDbHelper {
33 33 private static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N");
34 34
35 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 37 if (ks.getTable(cfName) != null) {
38 38 Path dumpFile = Files.createTempFile(dumpPrefix, null);
39 39 Files.deleteIfExists(dumpFile);
... ... @@ -45,7 +45,7 @@ public class CassandraDbHelper {
45 45 while (iter.hasNext()) {
46 46 Row row = iter.next();
47 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 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 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 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 108 int index = row.getColumnDefinitions().getIndexOf(column);
103 109 if (index > -1) {
  110 + String str;
104 111 DataType type = row.getColumnDefinitions().getType(index);
105 112 try {
106 113 if (row.isNull(index)) {
... ... @@ -123,8 +130,10 @@ public class CassandraDbHelper {
123 130 } catch (Exception e) {
124 131 str = "";
125 132 }
  133 + return str;
  134 + } else {
  135 + return defaultValue;
126 136 }
127   - return str;
128 137 }
129 138
130 139 private static String createInsertStatement(String cfName, String[] columns) {
... ...
... ... @@ -15,30 +15,31 @@
15 15 */
16 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 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 29 import org.thingsboard.server.common.data.asset.Asset;
29   -import org.thingsboard.server.common.data.asset.TenantAssetType;
30 30 import org.thingsboard.server.common.data.id.CustomerId;
31 31 import org.thingsboard.server.common.data.page.TextPageData;
32 32 import org.thingsboard.server.common.data.page.TextPageLink;
33 33 import org.thingsboard.server.common.data.security.Authority;
34 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 44 public abstract class BaseAssetControllerTest extends AbstractControllerTest {
44 45
... ... @@ -128,8 +129,8 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest {
128 129 asset.setType("typeA");
129 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 135 Assert.assertNotNull(assetTypes);
135 136 Assert.assertEquals(3, assetTypes.size());
... ...
... ... @@ -140,8 +140,8 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest {
140 140 device.setType("typeA");
141 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 146 Assert.assertNotNull(deviceTypes);
147 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 17
18 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 24 private TenantId tenantId;
  25 + private EntityType entityType;
  26 + private String type;
26 27
27   - public TenantDeviceType() {
  28 + public EntitySubtype() {
28 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 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 35 this.type = type;
42 36 }
43 37
... ... @@ -49,31 +43,52 @@ public class TenantDeviceType {
49 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 63 @Override
60 64 public boolean equals(Object o) {
61 65 if (this == o) return true;
62 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 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 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 90 sb.append('}');
77 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 16 package org.thingsboard.server.dao.asset;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.EntitySubtype;
19 20 import org.thingsboard.server.common.data.asset.Asset;
20   -import org.thingsboard.server.common.data.asset.TenantAssetType;
21 21 import org.thingsboard.server.common.data.page.TextPageLink;
22 22 import org.thingsboard.server.dao.Dao;
23 23
... ... @@ -112,6 +112,6 @@ public interface AssetDao extends Dao<Asset> {
112 112 *
113 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 16 package org.thingsboard.server.dao.asset;
17 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
  19 +import org.thingsboard.server.common.data.EntitySubtype;
19 20 import org.thingsboard.server.common.data.asset.Asset;
20   -import org.thingsboard.server.common.data.asset.TenantAssetType;
21 21 import org.thingsboard.server.common.data.id.AssetId;
22 22 import org.thingsboard.server.common.data.id.CustomerId;
23 23 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -61,5 +61,5 @@ public interface AssetService {
61 61
62 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 25 import org.springframework.stereotype.Service;
26 26 import org.springframework.util.StringUtils;
27 27 import org.thingsboard.server.common.data.Customer;
  28 +import org.thingsboard.server.common.data.EntitySubtype;
28 29 import org.thingsboard.server.common.data.EntityType;
29 30 import org.thingsboard.server.common.data.Tenant;
30 31 import org.thingsboard.server.common.data.asset.Asset;
31   -import org.thingsboard.server.common.data.asset.TenantAssetType;
32 32 import org.thingsboard.server.common.data.id.AssetId;
33 33 import org.thingsboard.server.common.data.id.CustomerId;
34 34 import org.thingsboard.server.common.data.id.EntityId;
... ... @@ -217,22 +217,15 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
217 217 }
218 218
219 219 @Override
220   - public ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId) {
  220 + public ListenableFuture<List<EntitySubtype>> findAssetTypesByTenantId(TenantId tenantId) {
221 221 log.trace("Executing findAssetTypesByTenantId, tenantId [{}]", tenantId);
222 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 227 return assetTypes;
234 228 });
235   - return tenantAssetTypes;
236 229 }
237 230
238 231 private DataValidator<Asset> assetValidator =
... ...
... ... @@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset;
17 17
18 18 import com.datastax.driver.core.ResultSet;
19 19 import com.datastax.driver.core.ResultSetFuture;
  20 +import com.datastax.driver.core.Statement;
20 21 import com.datastax.driver.core.querybuilder.Select;
21 22 import com.datastax.driver.mapping.Result;
22 23 import com.google.common.base.Function;
... ... @@ -24,11 +25,12 @@ import com.google.common.util.concurrent.Futures;
24 25 import com.google.common.util.concurrent.ListenableFuture;
25 26 import lombok.extern.slf4j.Slf4j;
26 27 import org.springframework.stereotype.Component;
  28 +import org.thingsboard.server.common.data.EntitySubtype;
  29 +import org.thingsboard.server.common.data.EntityType;
27 30 import org.thingsboard.server.common.data.asset.Asset;
28   -import org.thingsboard.server.common.data.asset.TenantAssetType;
29 31 import org.thingsboard.server.common.data.page.TextPageLink;
30 32 import org.thingsboard.server.dao.DaoUtil;
31   -import org.thingsboard.server.dao.model.TenantAssetTypeEntity;
  33 +import org.thingsboard.server.dao.model.EntitySubtypeEntity;
32 34 import org.thingsboard.server.dao.model.nosql.AssetEntity;
33 35 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
34 36 import org.thingsboard.server.dao.util.NoSqlDao;
... ... @@ -55,6 +57,16 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
55 57 }
56 58
57 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 70 public List<Asset> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink) {
59 71 log.debug("Try to find assets by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
60 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 142 }
131 143
132 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 153 @Nullable
139 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 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 163 } else {
145 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 17
18 18 import com.datastax.driver.core.ResultSet;
19 19 import com.datastax.driver.core.ResultSetFuture;
  20 +import com.datastax.driver.core.Statement;
20 21 import com.datastax.driver.core.querybuilder.Select;
21 22 import com.datastax.driver.mapping.Result;
22 23 import com.google.common.base.Function;
... ... @@ -25,10 +26,11 @@ import com.google.common.util.concurrent.ListenableFuture;
25 26 import lombok.extern.slf4j.Slf4j;
26 27 import org.springframework.stereotype.Component;
27 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 31 import org.thingsboard.server.common.data.page.TextPageLink;
30 32 import org.thingsboard.server.dao.DaoUtil;
31   -import org.thingsboard.server.dao.model.TenantDeviceTypeEntity;
  33 +import org.thingsboard.server.dao.model.EntitySubtypeEntity;
32 34 import org.thingsboard.server.dao.model.nosql.DeviceEntity;
33 35 import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
34 36 import org.thingsboard.server.dao.util.NoSqlDao;
... ... @@ -55,6 +57,16 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
55 57 }
56 58
57 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 70 public List<Device> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink) {
59 71 log.debug("Try to find devices by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
60 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 142 }
131 143
132 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 153 @Nullable
139 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 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 163 } else {
145 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 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 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 21 import org.thingsboard.server.common.data.page.TextPageLink;
22 22 import org.thingsboard.server.dao.Dao;
23 23
... ... @@ -113,5 +113,5 @@ public interface DeviceDao extends Dao<Device> {
113 113 *
114 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 17
18 18 import com.google.common.util.concurrent.ListenableFuture;
19 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 21 import org.thingsboard.server.common.data.id.CustomerId;
22 22 import org.thingsboard.server.common.data.id.DeviceId;
23 23 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -61,6 +61,6 @@ public interface DeviceService {
61 61
62 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 237 }
238 238
239 239 @Override
240   - public ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId) {
  240 + public ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId) {
241 241 log.trace("Executing findDeviceTypesByTenantId, tenantId [{}]", tenantId);
242 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 247 return deviceTypes;
254   - });
255   - return tenantDeviceTypes;
  248 + });
256 249 }
257 250
258 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 20 import com.datastax.driver.mapping.annotations.PartitionKey;
21 21 import com.datastax.driver.mapping.annotations.Table;
22 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 25 import org.thingsboard.server.common.data.id.TenantId;
  26 +import org.thingsboard.server.dao.model.type.EntityTypeCodec;
25 27
26 28 import java.util.UUID;
27 29
28 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 35 @Transient
34   - private static final long serialVersionUID = -1268181161886910152L;
  36 + private static final long serialVersionUID = -1268181961886910152L;
35 37
36 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 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 60 public UUID getTenantId() {
... ... @@ -68,40 +65,59 @@ public class TenantAssetTypeEntity {
68 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 85 @Override
79 86 public boolean equals(Object o) {
80 87 if (this == o) return true;
81 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 106 @Override
91 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 112 sb.append('}');
96 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 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 162 * Cassandra alarm constants.
155 163 */
156 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 19 import org.springframework.data.jpa.repository.Query;
20 20 import org.springframework.data.repository.CrudRepository;
21 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 24 import org.thingsboard.server.dao.model.sql.AssetEntity;
24 25 import org.thingsboard.server.dao.util.SqlDao;
25 26
... ... @@ -76,6 +77,7 @@ public interface AssetRepository extends CrudRepository<AssetEntity, String> {
76 77 @Param("idOffset") String idOffset,
77 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 20 import org.springframework.data.domain.PageRequest;
21 21 import org.springframework.data.repository.CrudRepository;
22 22 import org.springframework.stereotype.Component;
  23 +import org.thingsboard.server.common.data.EntitySubtype;
  24 +import org.thingsboard.server.common.data.EntityType;
23 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 27 import org.thingsboard.server.common.data.page.TextPageLink;
26 28 import org.thingsboard.server.dao.DaoUtil;
27 29 import org.thingsboard.server.dao.asset.AssetDao;
... ... @@ -29,10 +31,7 @@ import org.thingsboard.server.dao.model.sql.AssetEntity;
29 31 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
30 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 36 import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
38 37 import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs;
... ... @@ -121,7 +120,18 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao<AssetEntity, Asset> im
121 120 }
122 121
123 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 20 import org.springframework.data.repository.CrudRepository;
21 21 import org.springframework.data.repository.query.Param;
22 22 import org.thingsboard.server.dao.model.sql.DeviceEntity;
23   -import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity;
24 23 import org.thingsboard.server.dao.util.SqlDao;
25 24
26 25 import java.util.List;
... ... @@ -72,8 +71,8 @@ public interface DeviceRepository extends CrudRepository<DeviceEntity, String> {
72 71 @Param("idOffset") String idOffset,
73 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 77 DeviceEntity findByTenantIdAndName(String tenantId, String name);
79 78
... ...
... ... @@ -21,14 +21,14 @@ import org.springframework.data.domain.PageRequest;
21 21 import org.springframework.data.repository.CrudRepository;
22 22 import org.springframework.stereotype.Component;
23 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 26 import org.thingsboard.server.common.data.UUIDConverter;
26 27 import org.thingsboard.server.common.data.id.TenantId;
27 28 import org.thingsboard.server.common.data.page.TextPageLink;
28 29 import org.thingsboard.server.dao.DaoUtil;
29 30 import org.thingsboard.server.dao.device.DeviceDao;
30 31 import org.thingsboard.server.dao.model.sql.DeviceEntity;
31   -import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity;
32 32 import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
33 33 import org.thingsboard.server.dao.util.SqlDao;
34 34
... ... @@ -120,16 +120,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
120 120 }
121 121
122 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 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 135 return list;
... ...
... ... @@ -197,13 +197,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an
197 197 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
198 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 200 CREATE TABLE IF NOT EXISTS thingsboard.device_credentials (
208 201 id timeuuid PRIMARY KEY,
209 202 device_id timeuuid,
... ... @@ -270,12 +263,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and
270 263 PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
271 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 273 CREATE TABLE IF NOT EXISTS thingsboard.alarm (
281 274 id timeuuid,
... ...
... ... @@ -22,9 +22,9 @@ import org.junit.Assert;
22 22 import org.junit.Before;
23 23 import org.junit.Test;
24 24 import org.thingsboard.server.common.data.Customer;
  25 +import org.thingsboard.server.common.data.EntitySubtype;
25 26 import org.thingsboard.server.common.data.Tenant;
26 27 import org.thingsboard.server.common.data.asset.Asset;
27   -import org.thingsboard.server.common.data.asset.TenantAssetType;
28 28 import org.thingsboard.server.common.data.id.CustomerId;
29 29 import org.thingsboard.server.common.data.id.TenantId;
30 30 import org.thingsboard.server.common.data.page.TextPageData;
... ... @@ -181,7 +181,7 @@ public abstract class BaseAssetServiceTest extends AbstractServiceTest {
181 181 asset.setType("typeA");
182 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 185 Assert.assertNotNull(assetTypes);
186 186 Assert.assertEquals(3, assetTypes.size());
187 187 Assert.assertEquals("typeA", assetTypes.get(0).getType());
... ...
... ... @@ -23,8 +23,8 @@ import org.junit.Before;
23 23 import org.junit.Test;
24 24 import org.thingsboard.server.common.data.Customer;
25 25 import org.thingsboard.server.common.data.Device;
  26 +import org.thingsboard.server.common.data.EntitySubtype;
26 27 import org.thingsboard.server.common.data.Tenant;
27   -import org.thingsboard.server.common.data.TenantDeviceType;
28 28 import org.thingsboard.server.common.data.id.CustomerId;
29 29 import org.thingsboard.server.common.data.id.TenantId;
30 30 import org.thingsboard.server.common.data.page.TextPageData;
... ... @@ -191,7 +191,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
191 191 device.setType("typeA");
192 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 195 Assert.assertNotNull(deviceTypes);
196 196 Assert.assertEquals(3, deviceTypes.size());
197 197 Assert.assertEquals("typeA", deviceTypes.get(0).getType());
... ...
... ... @@ -19,8 +19,8 @@ import com.datastax.driver.core.utils.UUIDs;
19 19 import com.google.common.util.concurrent.ListenableFuture;
20 20 import org.junit.Test;
21 21 import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.thingsboard.server.common.data.EntitySubtype;
22 23 import org.thingsboard.server.common.data.asset.Asset;
23   -import org.thingsboard.server.common.data.asset.TenantAssetType;
24 24 import org.thingsboard.server.common.data.id.AssetId;
25 25 import org.thingsboard.server.common.data.id.CustomerId;
26 26 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -33,12 +33,9 @@ import java.util.List;
33 33 import java.util.Optional;
34 34 import java.util.UUID;
35 35 import java.util.concurrent.ExecutionException;
36   -import java.util.stream.Collectors;
37 36
38 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 41 * Created by Valerii Sosliuk on 5/21/2017.
... ... @@ -192,11 +189,10 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest {
192 189 saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_8", "TYPE_1");
193 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 197 assertEquals(3, tenant1Types.size());
202 198 assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_1")));
... ...