Browse Source

Improve device/asset types management.

pull/243/head
Igor Kulikov 9 years ago
parent
commit
ac3e4429b8
  1. 19
      application/src/main/data/upgrade/1.3.0/schema_update.cql
  2. 6
      application/src/main/java/org/thingsboard/server/controller/AssetController.java
  3. 6
      application/src/main/java/org/thingsboard/server/controller/DeviceController.java
  4. 47
      application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java
  5. 25
      application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java
  6. 37
      application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java
  7. 4
      application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java
  8. 63
      common/data/src/main/java/org/thingsboard/server/common/data/EntitySubtype.java
  9. 92
      common/data/src/main/java/org/thingsboard/server/common/data/asset/TenantAssetType.java
  10. 4
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java
  11. 4
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java
  12. 19
      dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
  13. 53
      dao/src/main/java/org/thingsboard/server/dao/asset/CassandraAssetDao.java
  14. 53
      dao/src/main/java/org/thingsboard/server/dao/device/CassandraDeviceDao.java
  15. 4
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java
  16. 4
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceService.java
  17. 19
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
  18. 123
      dao/src/main/java/org/thingsboard/server/dao/model/EntitySubtypeEntity.java
  19. 8
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  20. 107
      dao/src/main/java/org/thingsboard/server/dao/model/TenantAssetTypeEntity.java
  21. 107
      dao/src/main/java/org/thingsboard/server/dao/model/TenantDeviceTypeEntity.java
  22. 26
      dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantDeviceTypeEntity.java
  23. 8
      dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java
  24. 24
      dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java
  25. 5
      dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java
  26. 18
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
  27. 19
      dao/src/main/resources/cassandra/schema.cql
  28. 4
      dao/src/test/java/org/thingsboard/server/dao/service/BaseAssetServiceTest.java
  29. 4
      dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java
  30. 16
      dao/src/test/java/org/thingsboard/server/dao/sql/asset/JpaAssetDaoTest.java

19
application/src/main/data/upgrade/1.3.0/schema_update.cql

@ -69,13 +69,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an
PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS
SELECT *
from thingsboard.device
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( (type, tenant_id), id, customer_id)
WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);
DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_name;
DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_and_search_text;
DROP MATERIALIZED VIEW IF EXISTS thingsboard.asset_by_tenant_by_type_and_search_text;
@ -131,12 +124,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and
PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS
SELECT *
from thingsboard.asset
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( (type, tenant_id), id, customer_id)
WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);
CREATE TABLE IF NOT EXISTS thingsboard.entity_subtype (
tenant_id timeuuid,
entity_type text, // (DEVICE, ASSET)
type text,
PRIMARY KEY (tenant_id, entity_type, type)
);
CREATE TABLE IF NOT EXISTS thingsboard.alarm (
id timeuuid,

6
application/src/main/java/org/thingsboard/server/controller/AssetController.java

@ -20,8 +20,8 @@ import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
@ -246,11 +246,11 @@ public class AssetController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/asset/types", method = RequestMethod.GET)
@ResponseBody
public List<TenantAssetType> getAssetTypes() throws ThingsboardException {
public List<EntitySubtype> getAssetTypes() throws ThingsboardException {
try {
SecurityUser user = getCurrentUser();
TenantId tenantId = user.getTenantId();
ListenableFuture<List<TenantAssetType>> assetTypes = assetService.findAssetTypesByTenantId(tenantId);
ListenableFuture<List<EntitySubtype>> assetTypes = assetService.findAssetTypesByTenantId(tenantId);
return checkNotNull(assetTypes.get());
} catch (Exception e) {
throw handleException(e);

6
application/src/main/java/org/thingsboard/server/controller/DeviceController.java

@ -21,7 +21,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.TenantDeviceType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
@ -283,11 +283,11 @@ public class DeviceController extends BaseController {
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/device/types", method = RequestMethod.GET)
@ResponseBody
public List<TenantDeviceType> getDeviceTypes() throws ThingsboardException {
public List<EntitySubtype> getDeviceTypes() throws ThingsboardException {
try {
SecurityUser user = getCurrentUser();
TenantId tenantId = user.getTenantId();
ListenableFuture<List<TenantDeviceType>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId);
ListenableFuture<List<EntitySubtype>> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId);
return checkNotNull(deviceTypes.get());
} catch (Exception e) {
throw handleException(e);

47
application/src/main/java/org/thingsboard/server/service/install/CassandraDatabaseUpgradeService.java

@ -64,26 +64,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
log.info("Dumping devices ...");
Path devicesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device",
new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info"},
new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"},
new String[]{"", "", "", "", "", "", "default"},
"tb-devices");
if (devicesDump != null) {
CassandraDbHelper.appendToEndOfLine(devicesDump, "default");
}
log.info("Devices dumped.");
log.info("Dumping assets ...");
Path assetsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset",
new String[]{"id", "tenant_id", "customer_id", "name", "search_text", "additional_info", "type"},
new String[]{"", "", "", "", "", "", "default"},
"tb-assets");
log.info("Assets dumped.");
log.info("Dumping relations ...");
Path relationsDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "relation",
new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info"},
new String[]{"from_id", "from_type", "to_id", "to_type", "relation_type", "additional_info", "relation_type_group"},
new String[]{"", "", "", "", "", "", "COMMON"},
"tb-relations");
if (relationsDump != null) {
CassandraDbHelper.appendToEndOfLine(relationsDump, "COMMON");
}
log.info("Relations dumped.");
log.info("Updating schema ...");
@ -101,6 +98,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
}
log.info("Devices restored.");
log.info("Dumping device types ...");
Path deviceTypesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "device",
new String[]{"tenant_id", "type"},
new String[]{"", ""},
"tb-device-types");
if (deviceTypesDump != null) {
CassandraDbHelper.appendToEndOfLine(deviceTypesDump, "DEVICE");
}
log.info("Device types dumped.");
log.info("Loading device types ...");
if (deviceTypesDump != null) {
CassandraDbHelper.loadCf(ks, cluster.getSession(), "entity_subtype",
new String[]{"tenant_id", "type", "entity_type"}, deviceTypesDump);
Files.deleteIfExists(deviceTypesDump);
}
log.info("Device types loaded.");
log.info("Restoring assets ...");
if (assetsDump != null) {
CassandraDbHelper.loadCf(ks, cluster.getSession(), "asset",
@ -109,6 +123,23 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
}
log.info("Assets restored.");
log.info("Dumping asset types ...");
Path assetTypesDump = CassandraDbHelper.dumpCfIfExists(ks, cluster.getSession(), "asset",
new String[]{"tenant_id", "type"},
new String[]{"", ""},
"tb-asset-types");
if (assetTypesDump != null) {
CassandraDbHelper.appendToEndOfLine(assetTypesDump, "ASSET");
}
log.info("Asset types dumped.");
log.info("Loading asset types ...");
if (assetTypesDump != null) {
CassandraDbHelper.loadCf(ks, cluster.getSession(), "entity_subtype",
new String[]{"tenant_id", "type", "entity_type"}, assetTypesDump);
Files.deleteIfExists(assetTypesDump);
}
log.info("Asset types loaded.");
log.info("Restoring relations ...");
if (relationsDump != null) {
CassandraDbHelper.loadCf(ks, cluster.getSession(), "relation",

25
application/src/main/java/org/thingsboard/server/service/install/cql/CassandraDbHelper.java

@ -33,7 +33,7 @@ public class CassandraDbHelper {
private static final CSVFormat CSV_DUMP_FORMAT = CSVFormat.DEFAULT.withNullString("\\N");
public static Path dumpCfIfExists(KeyspaceMetadata ks, Session session, String cfName,
String[] columns, String dumpPrefix) throws Exception {
String[] columns, String[] defaultValues, String dumpPrefix) throws Exception {
if (ks.getTable(cfName) != null) {
Path dumpFile = Files.createTempFile(dumpPrefix, null);
Files.deleteIfExists(dumpFile);
@ -45,7 +45,7 @@ public class CassandraDbHelper {
while (iter.hasNext()) {
Row row = iter.next();
if (row != null) {
dumpRow(row, columns, csvPrinter);
dumpRow(row, columns, defaultValues, csvPrinter);
}
}
}
@ -89,18 +89,25 @@ public class CassandraDbHelper {
}
private static void dumpRow(Row row, String[] columns, CSVPrinter csvPrinter) throws Exception {
private static void dumpRow(Row row, String[] columns, String[] defaultValues, CSVPrinter csvPrinter) throws Exception {
List<String> record = new ArrayList<>();
for (String column : columns) {
record.add(getColumnValue(column, row));
for (int i=0;i<columns.length;i++) {
String column = columns[i];
String defaultValue;
if (defaultValues != null && i < defaultValues.length) {
defaultValue = defaultValues[i];
} else {
defaultValue = "";
}
record.add(getColumnValue(column, defaultValue, row));
}
csvPrinter.printRecord(record);
}
private static String getColumnValue(String column, Row row) {
String str = "";
private static String getColumnValue(String column, String defaultValue, Row row) {
int index = row.getColumnDefinitions().getIndexOf(column);
if (index > -1) {
String str;
DataType type = row.getColumnDefinitions().getType(index);
try {
if (row.isNull(index)) {
@ -123,8 +130,10 @@ public class CassandraDbHelper {
} catch (Exception e) {
str = "";
}
return str;
} else {
return defaultValue;
}
return str;
}
private static String createInsertStatement(String cfName, String[] columns) {

37
application/src/test/java/org/thingsboard/server/controller/BaseAssetControllerTest.java

@ -15,30 +15,31 @@
*/
package org.thingsboard.server.controller;
import static org.hamcrest.Matchers.containsString;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.lang3.RandomStringUtils;
import org.thingsboard.server.common.data.*;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.page.TextPageData;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.common.data.security.Authority;
import org.thingsboard.server.dao.model.ModelConstants;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.core.type.TypeReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
public abstract class BaseAssetControllerTest extends AbstractControllerTest {
@ -128,8 +129,8 @@ public abstract class BaseAssetControllerTest extends AbstractControllerTest {
asset.setType("typeA");
assets.add(doPost("/api/asset", asset, Asset.class));
}
List<TenantAssetType> assetTypes = doGetTyped("/api/asset/types",
new TypeReference<List<TenantAssetType>>(){});
List<EntitySubtype> assetTypes = doGetTyped("/api/asset/types",
new TypeReference<List<EntitySubtype>>(){});
Assert.assertNotNull(assetTypes);
Assert.assertEquals(3, assetTypes.size());

4
application/src/test/java/org/thingsboard/server/controller/BaseDeviceControllerTest.java

@ -140,8 +140,8 @@ public abstract class BaseDeviceControllerTest extends AbstractControllerTest {
device.setType("typeA");
devices.add(doPost("/api/device", device, Device.class));
}
List<TenantDeviceType> deviceTypes = doGetTyped("/api/device/types",
new TypeReference<List<TenantDeviceType>>(){});
List<EntitySubtype> deviceTypes = doGetTyped("/api/device/types",
new TypeReference<List<EntitySubtype>>(){});
Assert.assertNotNull(deviceTypes);
Assert.assertEquals(3, deviceTypes.size());

63
common/data/src/main/java/org/thingsboard/server/common/data/TenantDeviceType.java → common/data/src/main/java/org/thingsboard/server/common/data/EntitySubtype.java

@ -17,27 +17,21 @@ package org.thingsboard.server.common.data;
import org.thingsboard.server.common.data.id.TenantId;
public class TenantDeviceType {
public class EntitySubtype {
private static final long serialVersionUID = 8057240243859922101L;
private static final long serialVersionUID = 8057240243059922101L;
private String type;
private TenantId tenantId;
private EntityType entityType;
private String type;
public TenantDeviceType() {
public EntitySubtype() {
super();
}
public TenantDeviceType(String type, TenantId tenantId) {
this.type = type;
public EntitySubtype(TenantId tenantId, EntityType entityType, String type) {
this.tenantId = tenantId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.entityType = entityType;
this.type = type;
}
@ -49,31 +43,52 @@ public class TenantDeviceType {
this.tenantId = tenantId;
}
@Override
public int hashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
return result;
public EntityType getEntityType() {
return entityType;
}
public void setEntityType(EntityType entityType) {
this.entityType = entityType;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TenantDeviceType that = (TenantDeviceType) o;
EntitySubtype that = (EntitySubtype) o;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false;
if (entityType != that.entityType) return false;
return type != null ? type.equals(that.type) : that.type == null;
}
@Override
public int hashCode() {
int result = tenantId != null ? tenantId.hashCode() : 0;
result = 31 * result + (entityType != null ? entityType.hashCode() : 0);
result = 31 * result + (type != null ? type.hashCode() : 0);
return result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TenantDeviceType{");
sb.append("type='").append(type).append('\'');
sb.append(", tenantId=").append(tenantId);
final StringBuilder sb = new StringBuilder("EntitySubtype{");
sb.append("tenantId=").append(tenantId);
sb.append(", entityType=").append(entityType);
sb.append(", type='").append(type).append('\'');
sb.append('}');
return sb.toString();
}
}

92
common/data/src/main/java/org/thingsboard/server/common/data/asset/TenantAssetType.java

@ -1,92 +0,0 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.asset;
import org.thingsboard.server.common.data.UUIDConverter;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.UUID;
public class TenantAssetType {
private static final long serialVersionUID = 8057290243855622101L;
private String type;
private TenantId tenantId;
public TenantAssetType() {
super();
}
public TenantAssetType(String type, TenantId tenantId) {
this.type = type;
this.tenantId = tenantId;
}
public TenantAssetType(String type, UUID tenantId) {
this.type = type;
this.tenantId = new TenantId(tenantId);
}
public TenantAssetType(String type, String tenantId) {
this.type = type;
this.tenantId = new TenantId(UUIDConverter.fromString(tenantId));
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public TenantId getTenantId() {
return tenantId;
}
public void setTenantId(TenantId tenantId) {
this.tenantId = tenantId;
}
@Override
public int hashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TenantAssetType that = (TenantAssetType) o;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TenantAssetType{");
sb.append("type='").append(type).append('\'');
sb.append(", tenantId=").append(tenantId);
sb.append('}');
return sb.toString();
}
}

4
dao/src/main/java/org/thingsboard/server/dao/asset/AssetDao.java

@ -16,8 +16,8 @@
package org.thingsboard.server.dao.asset;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.Dao;
@ -112,6 +112,6 @@ public interface AssetDao extends Dao<Asset> {
*
* @return the list of tenant asset type objects
*/
ListenableFuture<List<TenantAssetType>> findTenantAssetTypesAsync();
ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId);
}

4
dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java

@ -16,8 +16,8 @@
package org.thingsboard.server.dao.asset;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
@ -61,5 +61,5 @@ public interface AssetService {
ListenableFuture<List<Asset>> findAssetsByQuery(AssetSearchQuery query);
ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId);
ListenableFuture<List<EntitySubtype>> findAssetTypesByTenantId(TenantId tenantId);
}

19
dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java

@ -25,10 +25,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId;
@ -217,22 +217,15 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
}
@Override
public ListenableFuture<List<TenantAssetType>> findAssetTypesByTenantId(TenantId tenantId) {
public ListenableFuture<List<EntitySubtype>> findAssetTypesByTenantId(TenantId tenantId) {
log.trace("Executing findAssetTypesByTenantId, tenantId [{}]", tenantId);
validateId(tenantId, "Incorrect tenantId " + tenantId);
ListenableFuture<List<TenantAssetType>> tenantAssetTypeEntities = assetDao.findTenantAssetTypesAsync();
ListenableFuture<List<TenantAssetType>> tenantAssetTypes = Futures.transform(tenantAssetTypeEntities,
(Function<List<TenantAssetType>, List<TenantAssetType>>) assetTypeEntities -> {
List<TenantAssetType> assetTypes = new ArrayList<>();
for (TenantAssetType assetType : assetTypeEntities) {
if (assetType.getTenantId().equals(tenantId)) {
assetTypes.add(assetType);
}
}
assetTypes.sort(Comparator.comparing(TenantAssetType::getType));
ListenableFuture<List<EntitySubtype>> tenantAssetTypes = assetDao.findTenantAssetTypesAsync(tenantId.getId());
return Futures.transform(tenantAssetTypes,
(Function<List<EntitySubtype>, List<EntitySubtype>>) assetTypes -> {
assetTypes.sort(Comparator.comparing(EntitySubtype::getType));
return assetTypes;
});
return tenantAssetTypes;
}
private DataValidator<Asset> assetValidator =

53
dao/src/main/java/org/thingsboard/server/dao/asset/CassandraAssetDao.java

@ -17,6 +17,7 @@ package org.thingsboard.server.dao.asset;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.mapping.Result;
import com.google.common.base.Function;
@ -24,11 +25,12 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.TenantAssetTypeEntity;
import org.thingsboard.server.dao.model.EntitySubtypeEntity;
import org.thingsboard.server.dao.model.nosql.AssetEntity;
import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
import org.thingsboard.server.dao.util.NoSqlDao;
@ -54,6 +56,16 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
return ASSET_COLUMN_FAMILY_NAME;
}
@Override
public Asset save(Asset domain) {
Asset savedAsset = super.save(domain);
EntitySubtype entitySubtype = new EntitySubtype(savedAsset.getTenantId(), EntityType.ASSET, savedAsset.getType());
EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
executeWrite(saveStatement);
return savedAsset;
}
@Override
public List<Asset> findAssetsByTenantId(UUID tenantId, TextPageLink pageLink) {
log.debug("Try to find assets by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
@ -130,36 +142,29 @@ public class CassandraAssetDao extends CassandraAbstractSearchTextDao<AssetEntit
}
@Override
public ListenableFuture<List<TenantAssetType>> findTenantAssetTypesAsync() {
Select statement = select().distinct().column(ASSET_TYPE_PROPERTY).column(ASSET_TENANT_ID_PROPERTY).from(ASSET_TYPES_BY_TENANT_VIEW_NAME);
statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
ResultSetFuture resultSetFuture = getSession().executeAsync(statement);
ListenableFuture<List<TenantAssetTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantAssetTypeEntity>>() {
public ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId) {
Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME);
Select.Where query = select.where();
query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.ASSET));
query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
ResultSetFuture resultSetFuture = getSession().executeAsync(query);
return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
@Nullable
@Override
public List<TenantAssetTypeEntity> apply(@Nullable ResultSet resultSet) {
Result<TenantAssetTypeEntity> result = cluster.getMapper(TenantAssetTypeEntity.class).map(resultSet);
public List<EntitySubtype> apply(@Nullable ResultSet resultSet) {
Result<EntitySubtypeEntity> result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet);
if (result != null) {
return result.all();
List<EntitySubtype> entitySubtypes = new ArrayList<>();
result.all().forEach((entitySubtypeEntity) ->
entitySubtypes.add(entitySubtypeEntity.toEntitySubtype())
);
return entitySubtypes;
} else {
return Collections.emptyList();
}
}
});
return Futures.transform(result, new Function<List<TenantAssetTypeEntity>, List<TenantAssetType>>() {
@Nullable
@Override
public List<TenantAssetType> apply(@Nullable List<TenantAssetTypeEntity> entityList) {
List<TenantAssetType> list = Collections.emptyList();
if (entityList != null && !entityList.isEmpty()) {
list = new ArrayList<>();
for (TenantAssetTypeEntity object : entityList) {
list.add(object.toTenantAssetType());
}
}
return list;
}
});
}
}

53
dao/src/main/java/org/thingsboard/server/dao/device/CassandraDeviceDao.java

@ -17,6 +17,7 @@ package org.thingsboard.server.dao.device;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.mapping.Result;
import com.google.common.base.Function;
@ -25,10 +26,11 @@ import com.google.common.util.concurrent.ListenableFuture;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.TenantDeviceType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.TenantDeviceTypeEntity;
import org.thingsboard.server.dao.model.EntitySubtypeEntity;
import org.thingsboard.server.dao.model.nosql.DeviceEntity;
import org.thingsboard.server.dao.nosql.CassandraAbstractSearchTextDao;
import org.thingsboard.server.dao.util.NoSqlDao;
@ -54,6 +56,16 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
return DEVICE_COLUMN_FAMILY_NAME;
}
@Override
public Device save(Device domain) {
Device savedDevice = super.save(domain);
EntitySubtype entitySubtype = new EntitySubtype(savedDevice.getTenantId(), EntityType.DEVICE, savedDevice.getType());
EntitySubtypeEntity entitySubtypeEntity = new EntitySubtypeEntity(entitySubtype);
Statement saveStatement = cluster.getMapper(EntitySubtypeEntity.class).saveQuery(entitySubtypeEntity);
executeWrite(saveStatement);
return savedDevice;
}
@Override
public List<Device> findDevicesByTenantId(UUID tenantId, TextPageLink pageLink) {
log.debug("Try to find devices by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
@ -130,36 +142,29 @@ public class CassandraDeviceDao extends CassandraAbstractSearchTextDao<DeviceEnt
}
@Override
public ListenableFuture<List<TenantDeviceType>> findTenantDeviceTypesAsync() {
Select statement = select().distinct().column(DEVICE_TYPE_PROPERTY).column(DEVICE_TENANT_ID_PROPERTY).from(DEVICE_TYPES_BY_TENANT_VIEW_NAME);
statement.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
ResultSetFuture resultSetFuture = getSession().executeAsync(statement);
ListenableFuture<List<TenantDeviceTypeEntity>> result = Futures.transform(resultSetFuture, new Function<ResultSet, List<TenantDeviceTypeEntity>>() {
public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) {
Select select = select().from(ENTITY_SUBTYPE_COLUMN_FAMILY_NAME);
Select.Where query = select.where();
query.and(eq(ENTITY_SUBTYPE_TENANT_ID_PROPERTY, tenantId));
query.and(eq(ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, EntityType.DEVICE));
query.setConsistencyLevel(cluster.getDefaultReadConsistencyLevel());
ResultSetFuture resultSetFuture = getSession().executeAsync(query);
return Futures.transform(resultSetFuture, new Function<ResultSet, List<EntitySubtype>>() {
@Nullable
@Override
public List<TenantDeviceTypeEntity> apply(@Nullable ResultSet resultSet) {
Result<TenantDeviceTypeEntity> result = cluster.getMapper(TenantDeviceTypeEntity.class).map(resultSet);
public List<EntitySubtype> apply(@Nullable ResultSet resultSet) {
Result<EntitySubtypeEntity> result = cluster.getMapper(EntitySubtypeEntity.class).map(resultSet);
if (result != null) {
return result.all();
List<EntitySubtype> entitySubtypes = new ArrayList<>();
result.all().forEach((entitySubtypeEntity) ->
entitySubtypes.add(entitySubtypeEntity.toEntitySubtype())
);
return entitySubtypes;
} else {
return Collections.emptyList();
}
}
});
return Futures.transform(result, new Function<List<TenantDeviceTypeEntity>, List<TenantDeviceType>>() {
@Nullable
@Override
public List<TenantDeviceType> apply(@Nullable List<TenantDeviceTypeEntity> entityList) {
List<TenantDeviceType> list = Collections.emptyList();
if (entityList != null && !entityList.isEmpty()) {
list = new ArrayList<>();
for (TenantDeviceTypeEntity object : entityList) {
list.add(object.toTenantDeviceType());
}
}
return list;
}
});
}
}

4
dao/src/main/java/org/thingsboard/server/dao/device/DeviceDao.java

@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.TenantDeviceType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.Dao;
@ -113,5 +113,5 @@ public interface DeviceDao extends Dao<Device> {
*
* @return the list of tenant device type objects
*/
ListenableFuture<List<TenantDeviceType>> findTenantDeviceTypesAsync();
ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId);
}

4
dao/src/main/java/org/thingsboard/server/dao/device/DeviceService.java

@ -17,7 +17,7 @@ package org.thingsboard.server.dao.device;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.TenantDeviceType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
@ -61,6 +61,6 @@ public interface DeviceService {
ListenableFuture<List<Device>> findDevicesByQuery(DeviceSearchQuery query);
ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId);
ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId);
}

19
dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java

@ -237,22 +237,15 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
}
@Override
public ListenableFuture<List<TenantDeviceType>> findDeviceTypesByTenantId(TenantId tenantId) {
public ListenableFuture<List<EntitySubtype>> findDeviceTypesByTenantId(TenantId tenantId) {
log.trace("Executing findDeviceTypesByTenantId, tenantId [{}]", tenantId);
validateId(tenantId, "Incorrect tenantId " + tenantId);
ListenableFuture<List<TenantDeviceType>> tenantDeviceTypeEntities = deviceDao.findTenantDeviceTypesAsync();
ListenableFuture<List<TenantDeviceType>> tenantDeviceTypes = Futures.transform(tenantDeviceTypeEntities,
(Function<List<TenantDeviceType>, List<TenantDeviceType>>) deviceTypeEntities -> {
List<TenantDeviceType> deviceTypes = new ArrayList<>();
for (TenantDeviceType deviceType : deviceTypeEntities) {
if (deviceType.getTenantId().equals(tenantId)) {
deviceTypes.add(deviceType);
}
}
deviceTypes.sort(Comparator.comparing(TenantDeviceType::getType));
ListenableFuture<List<EntitySubtype>> tenantDeviceTypes = deviceDao.findTenantDeviceTypesAsync(tenantId.getId());
return Futures.transform(tenantDeviceTypes,
(Function<List<EntitySubtype>, List<EntitySubtype>>) deviceTypes -> {
deviceTypes.sort(Comparator.comparing(EntitySubtype::getType));
return deviceTypes;
});
return tenantDeviceTypes;
});
}
private DataValidator<Device> deviceValidator =

123
dao/src/main/java/org/thingsboard/server/dao/model/EntitySubtypeEntity.java

@ -0,0 +1,123 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.model;
import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import com.datastax.driver.mapping.annotations.Transient;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.type.EntityTypeCodec;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.*;
@Table(name = ENTITY_SUBTYPE_COLUMN_FAMILY_NAME)
public class EntitySubtypeEntity {
@Transient
private static final long serialVersionUID = -1268181961886910152L;
@PartitionKey(value = 0)
@Column(name = ENTITY_SUBTYPE_TENANT_ID_PROPERTY)
private UUID tenantId;
@PartitionKey(value = 1)
@Column(name = ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY, codec = EntityTypeCodec.class)
private EntityType entityType;
@PartitionKey(value = 2)
@Column(name = ENTITY_SUBTYPE_TYPE_PROPERTY)
private String type;
public EntitySubtypeEntity() {
super();
}
public EntitySubtypeEntity(EntitySubtype entitySubtype) {
this.tenantId = entitySubtype.getTenantId().getId();
this.entityType = entitySubtype.getEntityType();
this.type = entitySubtype.getType();
}
public UUID getTenantId() {
return tenantId;
}
public void setTenantId(UUID tenantId) {
this.tenantId = tenantId;
}
public EntityType getEntityType() {
return entityType;
}
public void setEntityType(EntityType entityType) {
this.entityType = entityType;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EntitySubtypeEntity that = (EntitySubtypeEntity) o;
if (tenantId != null ? !tenantId.equals(that.tenantId) : that.tenantId != null) return false;
if (entityType != that.entityType) return false;
return type != null ? type.equals(that.type) : that.type == null;
}
@Override
public int hashCode() {
int result = tenantId != null ? tenantId.hashCode() : 0;
result = 31 * result + (entityType != null ? entityType.hashCode() : 0);
result = 31 * result + (type != null ? type.hashCode() : 0);
return result;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("EntitySubtypeEntity{");
sb.append("tenantId=").append(tenantId);
sb.append(", entityType=").append(entityType);
sb.append(", type='").append(type).append('\'');
sb.append('}');
return sb.toString();
}
public EntitySubtype toEntitySubtype() {
EntitySubtype entitySubtype = new EntitySubtype();
entitySubtype.setTenantId(new TenantId(tenantId));
entitySubtype.setEntityType(entityType);
entitySubtype.setType(type);
return entitySubtype;
}
}

8
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -150,6 +150,14 @@ public class ModelConstants {
public static final String ASSET_BY_TENANT_AND_NAME_VIEW_NAME = "asset_by_tenant_and_name";
public static final String ASSET_TYPES_BY_TENANT_VIEW_NAME = "asset_types_by_tenant";
/**
* Cassandra entity_subtype constants.
*/
public static final String ENTITY_SUBTYPE_COLUMN_FAMILY_NAME = "entity_subtype";
public static final String ENTITY_SUBTYPE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
public static final String ENTITY_SUBTYPE_ENTITY_TYPE_PROPERTY = "entity_type";
public static final String ENTITY_SUBTYPE_TYPE_PROPERTY = "type";
/**
* Cassandra alarm constants.
*/

107
dao/src/main/java/org/thingsboard/server/dao/model/TenantAssetTypeEntity.java

@ -1,107 +0,0 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.model;
import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import com.datastax.driver.mapping.annotations.Transient;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.*;
@Table(name = ASSET_TYPES_BY_TENANT_VIEW_NAME)
public class TenantAssetTypeEntity {
@Transient
private static final long serialVersionUID = -1268181161886910152L;
@PartitionKey(value = 0)
@Column(name = ASSET_TYPE_PROPERTY)
private String type;
@PartitionKey(value = 1)
@Column(name = ASSET_TENANT_ID_PROPERTY)
private UUID tenantId;
public TenantAssetTypeEntity() {
super();
}
public TenantAssetTypeEntity(TenantAssetType tenantAssetType) {
this.type = tenantAssetType.getType();
if (tenantAssetType.getTenantId() != null) {
this.tenantId = tenantAssetType.getTenantId().getId();
}
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public UUID getTenantId() {
return tenantId;
}
public void setTenantId(UUID tenantId) {
this.tenantId = tenantId;
}
@Override
public int hashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TenantAssetTypeEntity that = (TenantAssetTypeEntity) o;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TenantAssetTypeEntity{");
sb.append("type='").append(type).append('\'');
sb.append(", tenantId=").append(tenantId);
sb.append('}');
return sb.toString();
}
public TenantAssetType toTenantAssetType() {
TenantAssetType tenantAssetType = new TenantAssetType();
tenantAssetType.setType(type);
if (tenantId != null) {
tenantAssetType.setTenantId(new TenantId(tenantId));
}
return tenantAssetType;
}
}

107
dao/src/main/java/org/thingsboard/server/dao/model/TenantDeviceTypeEntity.java

@ -1,107 +0,0 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.model;
import com.datastax.driver.mapping.annotations.Column;
import com.datastax.driver.mapping.annotations.PartitionKey;
import com.datastax.driver.mapping.annotations.Table;
import com.datastax.driver.mapping.annotations.Transient;
import org.thingsboard.server.common.data.TenantDeviceType;
import org.thingsboard.server.common.data.id.TenantId;
import java.util.UUID;
import static org.thingsboard.server.dao.model.ModelConstants.*;
@Table(name = DEVICE_TYPES_BY_TENANT_VIEW_NAME)
public class TenantDeviceTypeEntity {
@Transient
private static final long serialVersionUID = -1268181166886910152L;
@PartitionKey(value = 0)
@Column(name = DEVICE_TYPE_PROPERTY)
private String type;
@PartitionKey(value = 1)
@Column(name = DEVICE_TENANT_ID_PROPERTY)
private UUID tenantId;
public TenantDeviceTypeEntity() {
super();
}
public TenantDeviceTypeEntity(TenantDeviceType tenantDeviceType) {
this.type = tenantDeviceType.getType();
if (tenantDeviceType.getTenantId() != null) {
this.tenantId = tenantDeviceType.getTenantId().getId();
}
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public UUID getTenantId() {
return tenantId;
}
public void setTenantId(UUID tenantId) {
this.tenantId = tenantId;
}
@Override
public int hashCode() {
int result = type != null ? type.hashCode() : 0;
result = 31 * result + (tenantId != null ? tenantId.hashCode() : 0);
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TenantDeviceTypeEntity that = (TenantDeviceTypeEntity) o;
if (type != null ? !type.equals(that.type) : that.type != null) return false;
return tenantId != null ? tenantId.equals(that.tenantId) : that.tenantId == null;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("TenantDeviceTypeEntity{");
sb.append("type='").append(type).append('\'');
sb.append(", tenantId=").append(tenantId);
sb.append('}');
return sb.toString();
}
public TenantDeviceType toTenantDeviceType() {
TenantDeviceType tenantDeviceType = new TenantDeviceType();
tenantDeviceType.setType(type);
if (tenantId != null) {
tenantDeviceType.setTenantId(new TenantId(tenantId));
}
return tenantDeviceType;
}
}

26
dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantDeviceTypeEntity.java

@ -1,26 +0,0 @@
/**
* Copyright © 2016-2017 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.dao.model.sql;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class TenantDeviceTypeEntity {
private String tenantId;
private String type;
}

8
dao/src/main/java/org/thingsboard/server/dao/sql/asset/AssetRepository.java

@ -19,7 +19,8 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.dao.model.sql.AssetEntity;
import org.thingsboard.server.dao.util.SqlDao;
@ -76,6 +77,7 @@ public interface AssetRepository extends CrudRepository<AssetEntity, String> {
@Param("idOffset") String idOffset,
Pageable pageable);
@Query("SELECT NEW org.thingsboard.server.common.data.asset.TenantAssetType(a.type, a.tenantId) FROM AssetEntity a GROUP BY a.tenantId, a.type")
List<TenantAssetType> findTenantAssetTypes();
@Query("SELECT DISTINCT a.type FROM AssetEntity a WHERE a.tenantId = :tenantId")
List<String> findTenantAssetTypes(@Param("tenantId") String tenantId);
}

24
dao/src/main/java/org/thingsboard/server/dao/sql/asset/JpaAssetDao.java

@ -20,8 +20,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.asset.AssetDao;
@ -29,10 +31,7 @@ import org.thingsboard.server.dao.model.sql.AssetEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import org.thingsboard.server.dao.util.SqlDao;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUIDs;
@ -121,7 +120,18 @@ public class JpaAssetDao extends JpaAbstractSearchTextDao<AssetEntity, Asset> im
}
@Override
public ListenableFuture<List<TenantAssetType>> findTenantAssetTypesAsync() {
return service.submit(() -> assetRepository.findTenantAssetTypes());
public ListenableFuture<List<EntitySubtype>> findTenantAssetTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantAssetTypesToDto(tenantId, assetRepository.findTenantAssetTypes(fromTimeUUID(tenantId))));
}
private List<EntitySubtype> convertTenantAssetTypesToDto(UUID tenantId, List<String> types) {
List<EntitySubtype> list = Collections.emptyList();
if (types != null && !types.isEmpty()) {
list = new ArrayList<>();
for (String type : types) {
list.add(new EntitySubtype(new TenantId(tenantId), EntityType.ASSET, type));
}
}
return list;
}
}

5
dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceRepository.java

@ -20,7 +20,6 @@ import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.dao.model.sql.DeviceEntity;
import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity;
import org.thingsboard.server.dao.util.SqlDao;
import java.util.List;
@ -72,8 +71,8 @@ public interface DeviceRepository extends CrudRepository<DeviceEntity, String> {
@Param("idOffset") String idOffset,
Pageable pageable);
@Query("SELECT DISTINCT NEW org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity(d.tenantId, d.type) FROM DeviceEntity d")
List<TenantDeviceTypeEntity> findTenantDeviceTypes();
@Query("SELECT DISTINCT d.type FROM DeviceEntity d WHERE d.tenantId = :tenantId")
List<String> findTenantDeviceTypes(@Param("tenantId") String tenantId);
DeviceEntity findByTenantIdAndName(String tenantId, String name);

18
dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java

@ -21,14 +21,14 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.TenantDeviceType;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.UUIDConverter;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.device.DeviceDao;
import org.thingsboard.server.dao.model.sql.DeviceEntity;
import org.thingsboard.server.dao.model.sql.TenantDeviceTypeEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import org.thingsboard.server.dao.util.SqlDao;
@ -120,16 +120,16 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao<DeviceEntity, Device>
}
@Override
public ListenableFuture<List<TenantDeviceType>> findTenantDeviceTypesAsync() {
return service.submit(() -> convertTenantDeviceTypeEntityToDto(deviceRepository.findTenantDeviceTypes()));
public ListenableFuture<List<EntitySubtype>> findTenantDeviceTypesAsync(UUID tenantId) {
return service.submit(() -> convertTenantDeviceTypesToDto(tenantId, deviceRepository.findTenantDeviceTypes(fromTimeUUID(tenantId))));
}
private List<TenantDeviceType> convertTenantDeviceTypeEntityToDto(List<TenantDeviceTypeEntity> entities) {
List<TenantDeviceType> list = Collections.emptyList();
if (entities != null && !entities.isEmpty()) {
private List<EntitySubtype> convertTenantDeviceTypesToDto(UUID tenantId, List<String> types) {
List<EntitySubtype> list = Collections.emptyList();
if (types != null && !types.isEmpty()) {
list = new ArrayList<>();
for (TenantDeviceTypeEntity entity : entities) {
list.add(new TenantDeviceType(entity.getType(), new TenantId(UUIDConverter.fromString(entity.getTenantId()))));
for (String type : types) {
list.add(new EntitySubtype(new TenantId(tenantId), EntityType.DEVICE, type));
}
}
return list;

19
dao/src/main/resources/cassandra/schema.cql

@ -197,13 +197,6 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_by_customer_by_type_an
PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.device_types_by_tenant AS
SELECT *
from thingsboard.device
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( (type, tenant_id), id, customer_id)
WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);
CREATE TABLE IF NOT EXISTS thingsboard.device_credentials (
id timeuuid PRIMARY KEY,
device_id timeuuid,
@ -270,12 +263,12 @@ CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_by_customer_by_type_and
PRIMARY KEY ( customer_id, tenant_id, type, search_text, id )
WITH CLUSTERING ORDER BY ( tenant_id DESC, type ASC, search_text ASC, id DESC );
CREATE MATERIALIZED VIEW IF NOT EXISTS thingsboard.asset_types_by_tenant AS
SELECT *
from thingsboard.asset
WHERE tenant_id IS NOT NULL AND customer_id IS NOT NULL AND type IS NOT NULL AND id IS NOT NULL
PRIMARY KEY ( (type, tenant_id), id, customer_id)
WITH CLUSTERING ORDER BY ( id ASC, customer_id DESC);
CREATE TABLE IF NOT EXISTS thingsboard.entity_subtype (
tenant_id timeuuid,
entity_type text, // (DEVICE, ASSET)
type text,
PRIMARY KEY (tenant_id, entity_type, type)
);
CREATE TABLE IF NOT EXISTS thingsboard.alarm (
id timeuuid,

4
dao/src/test/java/org/thingsboard/server/dao/service/BaseAssetServiceTest.java

@ -22,9 +22,9 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageData;
@ -181,7 +181,7 @@ public abstract class BaseAssetServiceTest extends AbstractServiceTest {
asset.setType("typeA");
assets.add(assetService.saveAsset(asset));
}
List<TenantAssetType> assetTypes = assetService.findAssetTypesByTenantId(tenantId).get();
List<EntitySubtype> assetTypes = assetService.findAssetTypesByTenantId(tenantId).get();
Assert.assertNotNull(assetTypes);
Assert.assertEquals(3, assetTypes.size());
Assert.assertEquals("typeA", assetTypes.get(0).getType());

4
dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceServiceTest.java

@ -23,8 +23,8 @@ import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantDeviceType;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.TextPageData;
@ -191,7 +191,7 @@ public abstract class BaseDeviceServiceTest extends AbstractServiceTest {
device.setType("typeA");
devices.add(deviceService.saveDevice(device));
}
List<TenantDeviceType> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId).get();
List<EntitySubtype> deviceTypes = deviceService.findDeviceTypesByTenantId(tenantId).get();
Assert.assertNotNull(deviceTypes);
Assert.assertEquals(3, deviceTypes.size());
Assert.assertEquals("typeA", deviceTypes.get(0).getType());

16
dao/src/test/java/org/thingsboard/server/dao/sql/asset/JpaAssetDaoTest.java

@ -19,8 +19,8 @@ import com.datastax.driver.core.utils.UUIDs;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.asset.TenantAssetType;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
@ -33,12 +33,9 @@ import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
/**
* Created by Valerii Sosliuk on 5/21/2017.
@ -192,11 +189,10 @@ public class JpaAssetDaoTest extends AbstractJpaDaoTest {
saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_8", "TYPE_1");
saveAsset(UUIDs.timeBased(), tenantId2, customerId2, "TEST_ASSET_9", "TYPE_1");
ListenableFuture<List<TenantAssetType>> tenantAssetTypesFuture = assetDao.findTenantAssetTypesAsync();
List<TenantAssetType> tenantAssetTypes = tenantAssetTypesFuture.get();
assertNotNull(tenantAssetTypes);
List<TenantAssetType> tenant1Types = tenantAssetTypes.stream().filter(t -> t.getTenantId().getId().equals(tenantId1)).collect(Collectors.toList());
List<TenantAssetType> tenant2Types = tenantAssetTypes.stream().filter(t -> t.getTenantId().getId().equals(tenantId2)).collect(Collectors.toList());
List<EntitySubtype> tenant1Types = assetDao.findTenantAssetTypesAsync(tenantId1).get();
assertNotNull(tenant1Types);
List<EntitySubtype> tenant2Types = assetDao.findTenantAssetTypesAsync(tenantId2).get();
assertNotNull(tenant2Types);
assertEquals(3, tenant1Types.size());
assertTrue(tenant1Types.stream().anyMatch(t -> t.getType().equals("TYPE_1")));

Loading…
Cancel
Save