Browse Source

Tenant and Device profiles DAO layer

pull/3477/head
Igor Kulikov 6 years ago
parent
commit
3ddf14668e
  1. 42
      application/src/main/data/upgrade/3.1.1/schema_update.sql
  2. 5
      application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
  3. 5
      application/src/main/java/org/thingsboard/server/actors/app/AppActor.java
  4. 7
      application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java
  5. 4
      application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java
  6. 10
      application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java
  7. 8
      application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java
  8. 2
      application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java
  9. 11
      application/src/main/java/org/thingsboard/server/service/queue/DefaultTenantRoutingInfoService.java
  10. 16
      application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java
  11. 49
      common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java
  12. 49
      common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileService.java
  13. 13
      common/data/src/main/java/org/thingsboard/server/common/data/Device.java
  14. 78
      common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java
  15. 41
      common/data/src/main/java/org/thingsboard/server/common/data/EntityInfo.java
  16. 2
      common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java
  17. 29
      common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java
  18. 76
      common/data/src/main/java/org/thingsboard/server/common/data/TenantProfile.java
  19. 43
      common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceProfileId.java
  20. 2
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java
  21. 4
      common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java
  22. 24
      common/data/src/main/java/org/thingsboard/server/common/data/id/HasId.java
  23. 25
      common/data/src/main/java/org/thingsboard/server/common/data/id/HasUUID.java
  24. 2
      common/data/src/main/java/org/thingsboard/server/common/data/id/IdBased.java
  25. 43
      common/data/src/main/java/org/thingsboard/server/common/data/id/TenantProfileId.java
  26. 2
      common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java
  27. 4
      dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java
  28. 40
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java
  29. 202
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
  30. 10
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceServiceImpl.java
  31. 26
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  32. 11
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java
  33. 117
      dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java
  34. 22
      dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java
  35. 108
      dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantProfileEntity.java
  36. 56
      dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java
  37. 83
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java
  38. 80
      dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantProfileDao.java
  39. 54
      dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantProfileRepository.java
  40. 40
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileDao.java
  41. 187
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java
  42. 27
      dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java
  43. 28
      dao/src/main/resources/sql/schema-entities-hsql.sql
  44. 28
      dao/src/main/resources/sql/schema-entities.sql
  45. 11
      dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java
  46. 262
      dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceProfileServiceTest.java
  47. 248
      dao/src/test/java/org/thingsboard/server/dao/service/BaseTenantProfileServiceTest.java
  48. 23
      dao/src/test/java/org/thingsboard/server/dao/service/sql/DeviceProfileServiceSqlTest.java
  49. 23
      dao/src/test/java/org/thingsboard/server/dao/service/sql/TenantProfileServiceSqlTest.java
  50. 2
      dao/src/test/resources/sql/hsql/drop-all-tables.sql
  51. 4
      dao/src/test/resources/sql/psql/drop-all-tables.sql
  52. 4
      dao/src/test/resources/sql/timescale/drop-all-tables.sql

42
application/src/main/data/upgrade/3.1.1/schema_update.sql

@ -0,0 +1,42 @@
--
-- Copyright © 2016-2020 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.
--
ALTER TABLE device ADD COLUMN device_profile_id uuid;
ALTER TABLE tenant ADD COLUMN tenant_profile_id uuid;
CREATE TABLE IF NOT EXISTS device_profile (
id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY,
created_time bigint NOT NULL,
name varchar(255),
profile_data varchar,
description varchar,
search_text varchar(255),
default boolean,
tenant_id uuid,
default_rule_chain_id uuid
);
CREATE TABLE IF NOT EXISTS tenant_profile (
id uuid NOT NULL CONSTRAINT tenant_profile_pkey PRIMARY KEY,
created_time bigint NOT NULL,
name varchar(255),
profile_data varchar,
description varchar,
search_text varchar(255),
default boolean,
isolated_tb_core boolean,
isolated_tb_rule_engine boolean
);

5
application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java

@ -58,6 +58,7 @@ import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.dao.nosql.CassandraBufferedRateExecutor;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.timeseries.TimeseriesService;
import org.thingsboard.server.dao.user.UserService;
@ -137,6 +138,10 @@ public class ActorSystemContext {
@Getter
private TenantService tenantService;
@Autowired
@Getter
private TenantProfileService tenantProfileService;
@Autowired
@Getter
private CustomerService customerService;

5
application/src/main/java/org/thingsboard/server/actors/app/AppActor.java

@ -27,6 +27,7 @@ import org.thingsboard.server.actors.service.DefaultActorService;
import org.thingsboard.server.actors.tenant.TenantActor;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageDataIterable;
@ -116,7 +117,9 @@ public class AppActor extends ContextAwareActor {
boolean isRuleEngine = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE);
boolean isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE);
for (Tenant tenant : tenantIterator) {
if (isCore || (isRuleEngine && !tenant.isIsolatedTbRuleEngine())) {
// TODO: Tenant Profile from cache
TenantProfile tenantProfile = systemContext.getTenantProfileService().findTenantProfileById(TenantId.SYS_TENANT_ID, tenant.getTenantProfileId());
if (isCore || (isRuleEngine && !tenantProfile.isIsolatedTbRuleEngine())) {
log.debug("[{}] Creating tenant actor", tenant.getId());
getOrCreateTenantActor(tenant.getId());
log.debug("[{}] Tenant actor created.", tenant.getId());

7
application/src/main/java/org/thingsboard/server/actors/tenant/TenantActor.java

@ -31,6 +31,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator;
import org.thingsboard.server.actors.service.DefaultActorService;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
@ -75,12 +76,16 @@ public class TenantActor extends RuleChainManagerActor {
// This Service may be started for specific tenant only.
Optional<TenantId> isolatedTenantId = systemContext.getServiceInfoProvider().getIsolatedTenant();
// TODO: Tenant Profile from cache
TenantProfile tenantProfile = systemContext.getTenantProfileService().findTenantProfileById(tenantId, tenant.getTenantProfileId());
isRuleEngineForCurrentTenant = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE);
isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE);
if (isRuleEngineForCurrentTenant) {
try {
if (isolatedTenantId.map(id -> id.equals(tenantId)).orElseGet(() -> !tenant.isIsolatedTbRuleEngine())) {
if (isolatedTenantId.map(id -> id.equals(tenantId)).orElseGet(() -> !tenantProfile.isIsolatedTbRuleEngine())) {
log.info("[{}] Going to init rule chains", tenantId);
initRuleChains();
} else {

4
application/src/main/java/org/thingsboard/server/install/ThingsboardInstallService.java

@ -175,6 +175,9 @@ public class ThingsboardInstallService {
case "3.1.0":
log.info("Upgrading ThingsBoard from version 3.1.0 to 3.1.1 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.1.0");
case "3.1.1":
log.info("Upgrading ThingsBoard from version 3.1.1 to 3.2.0 ...");
databaseEntitiesUpgradeService.upgradeDatabase("3.1.1");
log.info("Updating system data...");
systemDataLoaderService.updateSystemWidgets();
break;
@ -206,6 +209,7 @@ public class ThingsboardInstallService {
componentDiscoveryService.discoverComponents();
systemDataLoaderService.createSysAdmin();
systemDataLoaderService.createDefaultTenantProfile();
systemDataLoaderService.createAdminSettings();
systemDataLoaderService.loadSystemWidgets();
// systemDataLoaderService.loadSystemPlugins();

10
application/src/main/java/org/thingsboard/server/service/install/DefaultSystemDataLoaderService.java

@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.asset.Asset;
import org.thingsboard.server.common.data.id.CustomerId;
@ -49,6 +50,7 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.user.UserService;
import org.thingsboard.server.dao.widget.WidgetsBundleService;
@ -82,6 +84,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
@Autowired
private TenantService tenantService;
@Autowired
private TenantProfileService tenantProfileService;
@Autowired
private CustomerService customerService;
@ -110,6 +115,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
createUser(Authority.SYS_ADMIN, null, null, "sysadmin@thingsboard.org", "sysadmin");
}
@Override
public void createDefaultTenantProfile() throws Exception {
tenantProfileService.findOrCreateDefaultTenantProfile(TenantId.SYS_TENANT_ID);
}
@Override
public void createAdminSettings() throws Exception {
AdminSettings generalSettings = new AdminSettings();

8
application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseUpgradeService.java

@ -303,6 +303,14 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
log.info("Schema updated.");
}
break;
case "3.1.1":
try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
log.info("Updating schema ...");
schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.1.1", SCHEMA_UPDATE_SQL);
loadSql(schemaUpdateFile, conn);
log.info("Schema updated.");
}
break;
default:
throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
}

2
application/src/main/java/org/thingsboard/server/service/install/SystemDataLoaderService.java

@ -19,6 +19,8 @@ public interface SystemDataLoaderService {
void createSysAdmin() throws Exception;
void createDefaultTenantProfile() throws Exception;
void createAdminSettings() throws Exception;
void loadSystemWidgets() throws Exception;

11
application/src/main/java/org/thingsboard/server/service/queue/DefaultTenantRoutingInfoService.java

@ -19,7 +19,9 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.queue.discovery.TenantRoutingInfo;
import org.thingsboard.server.queue.discovery.TenantRoutingInfoService;
@ -31,15 +33,20 @@ public class DefaultTenantRoutingInfoService implements TenantRoutingInfoService
private final TenantService tenantService;
public DefaultTenantRoutingInfoService(TenantService tenantService) {
private final TenantProfileService tenantProfileService;
public DefaultTenantRoutingInfoService(TenantService tenantService, TenantProfileService tenantProfileService) {
this.tenantService = tenantService;
this.tenantProfileService = tenantProfileService;
}
@Override
public TenantRoutingInfo getRoutingInfo(TenantId tenantId) {
Tenant tenant = tenantService.findTenantById(tenantId);
if (tenant != null) {
return new TenantRoutingInfo(tenantId, tenant.isIsolatedTbCore(), tenant.isIsolatedTbRuleEngine());
// TODO: Tenant Profile from cache
TenantProfile tenantProfile = tenantProfileService.findTenantProfileById(tenantId, tenant.getTenantProfileId());
return new TenantRoutingInfo(tenantId, tenantProfile.isIsolatedTbCore(), tenantProfile.isIsolatedTbRuleEngine());
} else {
throw new RuntimeException("Tenant not found!");
}

16
application/src/main/java/org/thingsboard/server/service/transport/DefaultTransportApiService.java

@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.TenantId;
@ -40,6 +41,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
@ -77,6 +79,9 @@ public class DefaultTransportApiService implements TransportApiService {
@Autowired
private TenantService tenantService;
@Autowired
private TenantProfileService tenantProfileService;
@Autowired
private DeviceService deviceService;
@ -168,10 +173,13 @@ public class DefaultTransportApiService implements TransportApiService {
private ListenableFuture<TransportApiResponseMsg> handle(GetTenantRoutingInfoRequestMsg requestMsg) {
TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));
ListenableFuture<Tenant> tenantFuture = tenantService.findTenantByIdAsync(TenantId.SYS_TENANT_ID, tenantId);
return Futures.transform(tenantFuture, tenant -> TransportApiResponseMsg.newBuilder()
.setGetTenantRoutingInfoResponseMsg(GetTenantRoutingInfoResponseMsg.newBuilder().setIsolatedTbCore(tenant.isIsolatedTbCore())
.setIsolatedTbRuleEngine(tenant.isIsolatedTbRuleEngine()).build()).build(), dbCallbackExecutorService);
// TODO: Tenant Profile from cache
ListenableFuture<TenantProfile> tenantProfileFuture =
Futures.transform(tenantService.findTenantByIdAsync(TenantId.SYS_TENANT_ID, tenantId), tenant ->
tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, tenant.getTenantProfileId()), dbCallbackExecutorService);
return Futures.transform(tenantProfileFuture, tenantProfile -> TransportApiResponseMsg.newBuilder()
.setGetTenantRoutingInfoResponseMsg(GetTenantRoutingInfoResponseMsg.newBuilder().setIsolatedTbCore(tenantProfile.isIsolatedTbCore())
.setIsolatedTbRuleEngine(tenantProfile.isIsolatedTbRuleEngine()).build()).build(), dbCallbackExecutorService);
}
private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) {

49
common/dao-api/src/main/java/org/thingsboard/server/dao/device/DeviceProfileService.java

@ -0,0 +1,49 @@
/**
* Copyright © 2016-2020 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.device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
public interface DeviceProfileService {
DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId);
EntityInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId);
DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile);
void deleteDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId);
PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink);
PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink);
DeviceProfile createDefaultDeviceProfile(TenantId tenantId);
DeviceProfile findDefaultDeviceProfile(TenantId tenantId);
EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId);
boolean setDefaultDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId);
void deleteDeviceProfilesByTenantId(TenantId tenantId);
}

49
common/dao-api/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileService.java

@ -0,0 +1,49 @@
/**
* Copyright © 2016-2020 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.tenant;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
public interface TenantProfileService {
TenantProfile findTenantProfileById(TenantId tenantId, TenantProfileId tenantProfileId);
EntityInfo findTenantProfileInfoById(TenantId tenantId, TenantProfileId tenantProfileId);
TenantProfile saveTenantProfile(TenantId tenantId, TenantProfile tenantProfile);
void deleteTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId);
PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink);
PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink);
TenantProfile findOrCreateDefaultTenantProfile(TenantId tenantId);
TenantProfile findDefaultTenantProfile(TenantId tenantId);
EntityInfo findDefaultTenantProfileInfo(TenantId tenantId);
boolean setDefaultTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId);
void deleteTenantProfiles(TenantId tenantId);
}

13
common/data/src/main/java/org/thingsboard/server/common/data/Device.java

@ -18,6 +18,7 @@ package org.thingsboard.server.common.data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
@EqualsAndHashCode(callSuper = true)
@ -30,6 +31,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
private String name;
private String type;
private String label;
private DeviceProfileId deviceProfileId;
public Device() {
super();
@ -46,6 +48,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.name = device.getName();
this.type = device.getType();
this.label = device.getLabel();
this.deviceProfileId = device.getDeviceProfileId();
}
public TenantId getTenantId() {
@ -89,6 +92,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
this.label = label;
}
public DeviceProfileId getDeviceProfileId() {
return deviceProfileId;
}
public void setDeviceProfileId(DeviceProfileId deviceProfileId) {
this.deviceProfileId = deviceProfileId;
}
@Override
public String getSearchText() {
return getName();
@ -107,6 +118,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
builder.append(type);
builder.append(", label=");
builder.append(label);
builder.append(", deviceProfileId=");
builder.append(deviceProfileId);
builder.append(", additionalInfo=");
builder.append(getAdditionalInfo());
builder.append(", createdTime=");

78
common/data/src/main/java/org/thingsboard/server/common/data/DeviceProfile.java

@ -0,0 +1,78 @@
/**
* Copyright © 2016-2020 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;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.getJson;
import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.setJson;
@Data
@EqualsAndHashCode(callSuper = true)
public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName {
private TenantId tenantId;
private String name;
private String description;
private boolean isDefault;
private RuleChainId defaultRuleChainId;
private transient JsonNode profileData;
@JsonIgnore
private byte[] profileDataBytes;
public DeviceProfile() {
super();
}
public DeviceProfile(DeviceProfileId deviceProfileId) {
super(deviceProfileId);
}
public DeviceProfile(DeviceProfile deviceProfile) {
super(deviceProfile);
this.tenantId = deviceProfile.getTenantId();
this.name = deviceProfile.getName();
this.description = deviceProfile.getDescription();
this.isDefault = deviceProfile.isDefault();
this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId();
this.setProfileData(deviceProfile.getProfileData());
}
@Override
public String getSearchText() {
return getName();
}
@Override
public String getName() {
return name;
}
public JsonNode getProfileData() {
return getJson(() -> profileData, () -> profileDataBytes);
}
public void setProfileData(JsonNode data) {
setJson(data, json -> this.profileData = json, bytes -> this.profileDataBytes = bytes);
}
}

41
common/data/src/main/java/org/thingsboard/server/common/data/EntityInfo.java

@ -0,0 +1,41 @@
/**
* Copyright © 2016-2020 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;
import lombok.Data;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import org.thingsboard.server.common.data.id.HasId;
import java.util.UUID;
@Data
public class EntityInfo implements HasId<EntityId>, HasName {
private final EntityId id;
private final String name;
public EntityInfo(EntityId id, String name) {
this.id = id;
this.name = name;
}
public EntityInfo(UUID uuid, String type, String name) {
this.id = EntityIdFactory.getByTypeAndUuid(type, uuid);
this.name = name;
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/EntityType.java

@ -19,5 +19,5 @@ package org.thingsboard.server.common.data;
* @author Andrew Shvayka
*/
public enum EntityType {
TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE
TENANT, TENANT_PROFILE, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, DEVICE_PROFILE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE
}

29
common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java

@ -19,8 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.TenantId;
import com.fasterxml.jackson.databind.JsonNode;
import org.thingsboard.server.common.data.id.TenantProfileId;
@EqualsAndHashCode(callSuper = true)
public class Tenant extends ContactBased<TenantId> implements HasTenantId {
@ -29,8 +28,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
private String title;
private String region;
private boolean isolatedTbCore;
private boolean isolatedTbRuleEngine;
private TenantProfileId tenantProfileId;
public Tenant() {
super();
@ -44,6 +42,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
super(tenant);
this.title = tenant.getTitle();
this.region = tenant.getRegion();
this.tenantProfileId = tenant.getTenantProfileId();
}
public String getTitle() {
@ -74,20 +73,12 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
this.region = region;
}
public boolean isIsolatedTbCore() {
return isolatedTbCore;
}
public void setIsolatedTbCore(boolean isolatedTbCore) {
this.isolatedTbCore = isolatedTbCore;
}
public boolean isIsolatedTbRuleEngine() {
return isolatedTbRuleEngine;
public TenantProfileId getTenantProfileId() {
return tenantProfileId;
}
public void setIsolatedTbRuleEngine(boolean isolatedTbRuleEngine) {
this.isolatedTbRuleEngine = isolatedTbRuleEngine;
public void setTenantProfileId(TenantProfileId tenantProfileId) {
this.tenantProfileId = tenantProfileId;
}
@Override
@ -102,10 +93,8 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
builder.append(title);
builder.append(", region=");
builder.append(region);
builder.append(", isolatedTbCore=");
builder.append(isolatedTbCore);
builder.append(", isolatedTbRuleEngine=");
builder.append(isolatedTbRuleEngine);
builder.append(", tenantProfileId=");
builder.append(tenantProfileId);
builder.append(", additionalInfo=");
builder.append(getAdditionalInfo());
builder.append(", country=");

76
common/data/src/main/java/org/thingsboard/server/common/data/TenantProfile.java

@ -0,0 +1,76 @@
/**
* Copyright © 2016-2020 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;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.TenantProfileId;
import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.getJson;
import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.setJson;
@Data
@EqualsAndHashCode(callSuper = true)
public class TenantProfile extends SearchTextBased<TenantProfileId> implements HasName {
private String name;
private String description;
private boolean isDefault;
private boolean isolatedTbCore;
private boolean isolatedTbRuleEngine;
private transient JsonNode profileData;
@JsonIgnore
private byte[] profileDataBytes;
public TenantProfile() {
super();
}
public TenantProfile(TenantProfileId tenantProfileId) {
super(tenantProfileId);
}
public TenantProfile(TenantProfile tenantProfile) {
super(tenantProfile);
this.name = tenantProfile.getName();
this.description = tenantProfile.getDescription();
this.isDefault = tenantProfile.isDefault();
this.isolatedTbCore = tenantProfile.isIsolatedTbCore();
this.isolatedTbRuleEngine = tenantProfile.isIsolatedTbRuleEngine();
this.setProfileData(tenantProfile.getProfileData());
}
@Override
public String getSearchText() {
return getName();
}
@Override
public String getName() {
return name;
}
public JsonNode getProfileData() {
return getJson(() -> profileData, () -> profileDataBytes);
}
public void setProfileData(JsonNode data) {
setJson(data, json -> this.profileData = json, bytes -> this.profileDataBytes = bytes);
}
}

43
common/data/src/main/java/org/thingsboard/server/common/data/id/DeviceProfileId.java

@ -0,0 +1,43 @@
/**
* Copyright © 2016-2020 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.id;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.thingsboard.server.common.data.EntityType;
public class DeviceProfileId extends UUIDBased implements EntityId {
private static final long serialVersionUID = 1L;
@JsonCreator
public DeviceProfileId(@JsonProperty("id") UUID id) {
super(id);
}
public static DeviceProfileId fromString(String deviceProfileId) {
return new DeviceProfileId(UUID.fromString(deviceProfileId));
}
@JsonIgnore
@Override
public EntityType getEntityType() {
return EntityType.DEVICE_PROFILE;
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityId.java

@ -29,7 +29,7 @@ import java.util.UUID;
@JsonDeserialize(using = EntityIdDeserializer.class)
@JsonSerialize(using = EntityIdSerializer.class)
public interface EntityId extends Serializable { //NOSONAR, the constant is closely related to EntityId
public interface EntityId extends HasUUID, Serializable { //NOSONAR, the constant is closely related to EntityId
UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080");

4
common/data/src/main/java/org/thingsboard/server/common/data/id/EntityIdFactory.java

@ -62,6 +62,10 @@ public class EntityIdFactory {
return new WidgetsBundleId(uuid);
case WIDGET_TYPE:
return new WidgetTypeId(uuid);
case DEVICE_PROFILE:
return new DeviceProfileId(uuid);
case TENANT_PROFILE:
return new TenantProfileId(uuid);
}
throw new IllegalArgumentException("EntityType " + type + " is not supported!");
}

24
common/data/src/main/java/org/thingsboard/server/common/data/id/HasId.java

@ -0,0 +1,24 @@
/**
* Copyright © 2016-2020 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.id;
import java.io.Serializable;
public interface HasId<I extends HasUUID> extends Serializable {
I getId();
}

25
common/data/src/main/java/org/thingsboard/server/common/data/id/HasUUID.java

@ -0,0 +1,25 @@
/**
* Copyright © 2016-2020 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.id;
import java.util.UUID;
public interface HasUUID {
UUID getId();
}

2
common/data/src/main/java/org/thingsboard/server/common/data/id/IdBased.java

@ -20,7 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.util.UUID;
public abstract class IdBased<I extends UUIDBased> implements Serializable {
public abstract class IdBased<I extends UUIDBased> implements HasId<I> {
protected I id;

43
common/data/src/main/java/org/thingsboard/server/common/data/id/TenantProfileId.java

@ -0,0 +1,43 @@
/**
* Copyright © 2016-2020 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.id;
import java.util.UUID;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.thingsboard.server.common.data.EntityType;
public class TenantProfileId extends UUIDBased implements EntityId {
private static final long serialVersionUID = 1L;
@JsonCreator
public TenantProfileId(@JsonProperty("id") UUID id) {
super(id);
}
public static TenantProfileId fromString(String tenantProfileId) {
return new TenantProfileId(UUID.fromString(tenantProfileId));
}
@JsonIgnore
@Override
public EntityType getEntityType() {
return EntityType.TENANT_PROFILE;
}
}

2
common/data/src/main/java/org/thingsboard/server/common/data/id/UUIDBased.java

@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.id;
import java.io.Serializable;
import java.util.UUID;
public abstract class UUIDBased implements Serializable {
public abstract class UUIDBased implements HasUUID, Serializable {
private static final long serialVersionUID = 1L;

4
dao/src/main/java/org/thingsboard/server/dao/DaoUtil.java

@ -43,6 +43,10 @@ public abstract class DaoUtil {
return new PageData(data, page.getTotalPages(), page.getTotalElements(), page.hasNext());
}
public static <T> PageData<T> pageToPageData(Page<T> page) {
return new PageData(page.getContent(), page.getTotalPages(), page.getTotalElements(), page.hasNext());
}
public static Pageable toPageable(PageLink pageLink) {
return toPageable(pageLink, Collections.emptyMap());
}

40
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileDao.java

@ -0,0 +1,40 @@
/**
* Copyright © 2016-2020 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.device;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao;
import java.util.UUID;
public interface DeviceProfileDao extends Dao<DeviceProfile> {
EntityInfo findDeviceProfileInfoById(TenantId tenantId, UUID deviceProfileId);
DeviceProfile save(TenantId tenantId, DeviceProfile deviceProfile);
PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink);
PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink);
DeviceProfile findDefaultDeviceProfile(TenantId tenantId);
EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId);
}

202
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -0,0 +1,202 @@
/**
* Copyright © 2016-2020 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.device;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.tenant.TenantDao;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Service
@Slf4j
public class DeviceProfileServiceImpl extends AbstractEntityService implements DeviceProfileService {
private static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId ";
@Autowired
private DeviceProfileDao deviceProfileDao;
@Autowired
private TenantDao tenantDao;
@Override
public DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
return deviceProfileDao.findById(tenantId, deviceProfileId.getId());
}
@Override
public EntityInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
return deviceProfileDao.findDeviceProfileInfoById(tenantId, deviceProfileId.getId());
}
@Override
public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) {
log.trace("Executing saveDeviceProfile [{}]", deviceProfile);
deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId);
DeviceProfile savedDeviceProfile;
try {
savedDeviceProfile = deviceProfileDao.save(deviceProfile.getTenantId(), deviceProfile);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_profile_name_unq_key")) {
throw new DataValidationException("Device profile with such name already exists!");
} else {
throw t;
}
}
return savedDeviceProfile;
}
@Override
public void deleteDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing deleteDeviceProfile [{}]", deviceProfileId);
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
deleteEntityRelations(tenantId, deviceProfileId);
deviceProfileDao.removeById(tenantId, deviceProfileId.getId());
}
@Override
public PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findDeviceProfiles tenantId [{}], pageLink [{}]", tenantId, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Validator.validatePageLink(pageLink);
return deviceProfileDao.findDeviceProfiles(tenantId, pageLink);
}
@Override
public PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findDeviceProfileInfos tenantId [{}], pageLink [{}]", tenantId, pageLink);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
Validator.validatePageLink(pageLink);
return deviceProfileDao.findDeviceProfileInfos(tenantId, pageLink);
}
@Override
public DeviceProfile createDefaultDeviceProfile(TenantId tenantId) {
log.trace("Executing createDefaultDeviceProfile tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
DeviceProfile deviceProfile = new DeviceProfile();
deviceProfile.setTenantId(tenantId);
deviceProfile.setDefault(true);
deviceProfile.setName("Default");
deviceProfile.setDescription("Default device profile");
deviceProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
return deviceProfileDao.save(tenantId, deviceProfile);
}
@Override
public DeviceProfile findDefaultDeviceProfile(TenantId tenantId) {
log.trace("Executing findDefaultDeviceProfile tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
return deviceProfileDao.findDefaultDeviceProfile(tenantId);
}
@Override
public EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId) {
log.trace("Executing findDefaultDeviceProfileInfo tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
return deviceProfileDao.findDefaultDeviceProfileInfo(tenantId);
}
@Override
public boolean setDefaultDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
log.trace("Executing setDefaultDeviceProfile [{}]", deviceProfileId);
Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
DeviceProfile deviceProfile = deviceProfileDao.findById(tenantId, deviceProfileId.getId());
if (!deviceProfile.isDefault()) {
deviceProfile.setDefault(true);
DeviceProfile previousDefaultDeviceProfile = findDefaultDeviceProfile(tenantId);
if (previousDefaultDeviceProfile == null) {
deviceProfileDao.save(tenantId, deviceProfile);
return true;
} else if (!previousDefaultDeviceProfile.getId().equals(deviceProfile.getId())) {
previousDefaultDeviceProfile.setDefault(false);
deviceProfileDao.save(tenantId, previousDefaultDeviceProfile);
deviceProfileDao.save(tenantId, deviceProfile);
return true;
}
}
return false;
}
@Override
public void deleteDeviceProfilesByTenantId(TenantId tenantId) {
log.trace("Executing deleteDeviceProfilesByTenantId, tenantId [{}]", tenantId);
validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
tenantDeviceProfilesRemover.removeEntities(tenantId, tenantId);
}
private DataValidator<DeviceProfile> deviceProfileValidator =
new DataValidator<DeviceProfile>() {
@Override
protected void validateDataImpl(TenantId tenantId, DeviceProfile deviceProfile) {
if (StringUtils.isEmpty(deviceProfile.getName())) {
throw new DataValidationException("Device profile name should be specified!");
}
if (deviceProfile.getTenantId() == null) {
throw new DataValidationException("Device profile should be assigned to tenant!");
} else {
Tenant tenant = tenantDao.findById(deviceProfile.getTenantId(), deviceProfile.getTenantId().getId());
if (tenant == null) {
throw new DataValidationException("Device profile is referencing to non-existent tenant!");
}
}
if (deviceProfile.isDefault()) {
DeviceProfile defaultDeviceProfile = findDefaultDeviceProfile(tenantId);
if (defaultDeviceProfile != null && !defaultDeviceProfile.getId().equals(deviceProfile.getId())) {
throw new DataValidationException("Another default device profile is present in scope of current tenant!");
}
}
}
};
private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover =
new PaginatedRemover<TenantId, DeviceProfile>() {
@Override
protected PageData<DeviceProfile> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
return deviceProfileDao.findDeviceProfiles(id, pageLink);
}
@Override
protected void removeEntity(TenantId tenantId, DeviceProfile entity) {
deleteDeviceProfile(tenantId, new DeviceProfileId(entity.getUuidId()));
}
};
}

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

@ -34,6 +34,8 @@ import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceInfo;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.EntitySubtype;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.EntityView;
@ -41,6 +43,7 @@ import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.device.DeviceSearchQuery;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
@ -95,6 +98,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
@Autowired
private DeviceCredentialsService deviceCredentialsService;
@Autowired
private DeviceProfileService deviceProfileService;
@Autowired
private EntityViewService entityViewService;
@ -159,6 +165,10 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
deviceValidator.validate(device, Device::getTenantId);
Device savedDevice;
try {
if (device.getDeviceProfileId() == null) {
EntityInfo deviceProfile = this.deviceProfileService.findDefaultDeviceProfileInfo(device.getTenantId());
device.setDeviceProfileId(new DeviceProfileId(deviceProfile.getId().getId()));
}
savedDevice = deviceDao.save(device.getTenantId(), device);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);

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

@ -114,11 +114,21 @@ public class ModelConstants {
public static final String TENANT_TITLE_PROPERTY = TITLE_PROPERTY;
public static final String TENANT_REGION_PROPERTY = "region";
public static final String TENANT_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
public static final String TENANT_ISOLATED_TB_CORE = "isolated_tb_core";
public static final String TENANT_ISOLATED_TB_RULE_ENGINE = "isolated_tb_rule_engine";
public static final String TENANT_TENANT_PROFILE_ID_PROPERTY = "tenant_profile_id";
public static final String TENANT_BY_REGION_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "tenant_by_region_and_search_text";
/**
* Tenant profile constants.
*/
public static final String TENANT_PROFILE_COLUMN_FAMILY_NAME = "tenant_profile";
public static final String TENANT_PROFILE_NAME_PROPERTY = "name";
public static final String TENANT_PROFILE_PROFILE_DATA_PROPERTY = "profile_data";
public static final String TENANT_PROFILE_DESCRIPTION_PROPERTY = "description";
public static final String TENANT_PROFILE_IS_DEFAULT_PROPERTY = "is_default";
public static final String TENANT_PROFILE_ISOLATED_TB_CORE = "isolated_tb_core";
public static final String TENANT_PROFILE_ISOLATED_TB_RULE_ENGINE = "isolated_tb_rule_engine";
/**
* Cassandra customer constants.
*/
@ -141,6 +151,7 @@ public class ModelConstants {
public static final String DEVICE_TYPE_PROPERTY = "type";
public static final String DEVICE_LABEL_PROPERTY = "label";
public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
public static final String DEVICE_DEVICE_PROFILE_ID_PROPERTY = "device_profile_id";
public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text";
public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text";
public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text";
@ -148,6 +159,17 @@ public class ModelConstants {
public static final String DEVICE_BY_TENANT_AND_NAME_VIEW_NAME = "device_by_tenant_and_name";
public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant";
/**
* Device profile constants.
*/
public static final String DEVICE_PROFILE_COLUMN_FAMILY_NAME = "device_profile";
public static final String DEVICE_PROFILE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
public static final String DEVICE_PROFILE_NAME_PROPERTY = "name";
public static final String DEVICE_PROFILE_PROFILE_DATA_PROPERTY = "profile_data";
public static final String DEVICE_PROFILE_DESCRIPTION_PROPERTY = "description";
public static final String DEVICE_PROFILE_IS_DEFAULT_PROPERTY = "is_default";
public static final String DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY = "default_rule_chain_id";
/**
* Cassandra entityView constants.
*/

11
dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java

@ -23,6 +23,7 @@ import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
@ -61,6 +62,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
@Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY)
private JsonNode additionalInfo;
@Column(name = ModelConstants.DEVICE_DEVICE_PROFILE_ID_PROPERTY, columnDefinition = "uuid")
private UUID deviceProfileId;
public AbstractDeviceEntity() {
super();
}
@ -76,6 +80,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
if (device.getCustomerId() != null) {
this.customerId = device.getCustomerId().getId();
}
if (device.getDeviceProfileId() != null) {
this.deviceProfileId = device.getDeviceProfileId().getId();
}
this.name = device.getName();
this.type = device.getType();
this.label = device.getLabel();
@ -87,6 +94,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
this.setCreatedTime(deviceEntity.getCreatedTime());
this.tenantId = deviceEntity.getTenantId();
this.customerId = deviceEntity.getCustomerId();
this.deviceProfileId = deviceEntity.getDeviceProfileId();
this.type = deviceEntity.getType();
this.name = deviceEntity.getName();
this.label = deviceEntity.getLabel();
@ -113,6 +121,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
if (customerId != null) {
device.setCustomerId(new CustomerId(customerId));
}
if (deviceProfileId != null) {
device.setDeviceProfileId(new DeviceProfileId(deviceProfileId));
}
device.setName(name);
device.setType(type);
device.setLabel(label);

117
dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceProfileEntity.java

@ -0,0 +1,117 @@
/**
* Copyright © 2016-2020 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 com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.SearchTextEntity;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.UUID;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@TypeDef(name = "json", typeClass = JsonStringType.class)
@Table(name = ModelConstants.DEVICE_PROFILE_COLUMN_FAMILY_NAME)
public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> implements SearchTextEntity<DeviceProfile> {
@Column(name = ModelConstants.DEVICE_PROFILE_TENANT_ID_PROPERTY)
private UUID tenantId;
@Column(name = ModelConstants.DEVICE_PROFILE_NAME_PROPERTY)
private String name;
@Column(name = ModelConstants.DEVICE_PROFILE_DESCRIPTION_PROPERTY)
private String description;
@Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
private String searchText;
@Column(name = ModelConstants.DEVICE_PROFILE_IS_DEFAULT_PROPERTY)
private boolean isDefault;
@Column(name = ModelConstants.DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY, columnDefinition = "uuid")
private UUID defaultRuleChainId;
@Type(type = "json")
@Column(name = ModelConstants.DEVICE_PROFILE_PROFILE_DATA_PROPERTY)
private JsonNode profileData;
public DeviceProfileEntity() {
super();
}
public DeviceProfileEntity(DeviceProfile deviceProfile) {
if (deviceProfile.getId() != null) {
this.setUuid(deviceProfile.getId().getId());
}
if (deviceProfile.getTenantId() != null) {
this.tenantId = deviceProfile.getTenantId().getId();
}
this.setCreatedTime(deviceProfile.getCreatedTime());
this.name = deviceProfile.getName();
this.description = deviceProfile.getDescription();
this.isDefault = deviceProfile.isDefault();
this.profileData = deviceProfile.getProfileData();
if (deviceProfile.getDefaultRuleChainId() != null) {
this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId().getId();
}
}
@Override
public String getSearchTextSource() {
return name;
}
@Override
public void setSearchText(String searchText) {
this.searchText = searchText;
}
public String getSearchText() {
return searchText;
}
@Override
public DeviceProfile toData() {
DeviceProfile deviceProfile = new DeviceProfile(new DeviceProfileId(this.getUuid()));
deviceProfile.setCreatedTime(createdTime);
if (tenantId != null) {
deviceProfile.setTenantId(new TenantId(tenantId));
}
deviceProfile.setName(name);
deviceProfile.setDescription(description);
deviceProfile.setDefault(isDefault);
deviceProfile.setProfileData(profileData);
if (defaultRuleChainId != null) {
deviceProfile.setDefaultRuleChainId(new RuleChainId(defaultRuleChainId));
}
return deviceProfile;
}
}

22
dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java

@ -21,7 +21,9 @@ import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.SearchTextEntity;
@ -30,6 +32,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.UUID;
@Data
@EqualsAndHashCode(callSuper = true)
@ -71,16 +74,13 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
@Column(name = ModelConstants.EMAIL_PROPERTY)
private String email;
@Column(name = ModelConstants.TENANT_ISOLATED_TB_CORE)
private boolean isolatedTbCore;
@Column(name = ModelConstants.TENANT_ISOLATED_TB_RULE_ENGINE)
private boolean isolatedTbRuleEngine;
@Type(type = "json")
@Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY)
private JsonNode additionalInfo;
@Column(name = ModelConstants.TENANT_TENANT_PROFILE_ID_PROPERTY, columnDefinition = "uuid")
private UUID tenantProfileId;
public TenantEntity() {
super();
}
@ -101,8 +101,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
this.phone = tenant.getPhone();
this.email = tenant.getEmail();
this.additionalInfo = tenant.getAdditionalInfo();
this.isolatedTbCore = tenant.isIsolatedTbCore();
this.isolatedTbRuleEngine = tenant.isIsolatedTbRuleEngine();
if (tenant.getTenantProfileId() != null) {
this.tenantProfileId = tenant.getTenantProfileId().getId();
}
}
@Override
@ -134,8 +135,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
tenant.setPhone(phone);
tenant.setEmail(email);
tenant.setAdditionalInfo(additionalInfo);
tenant.setIsolatedTbCore(isolatedTbCore);
tenant.setIsolatedTbRuleEngine(isolatedTbRuleEngine);
if (tenantProfileId != null) {
tenant.setTenantProfileId(new TenantProfileId(tenantProfileId));
}
return tenant;
}

108
dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantProfileEntity.java

@ -0,0 +1,108 @@
/**
* Copyright © 2016-2020 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 com.fasterxml.jackson.databind.JsonNode;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.dao.model.BaseSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.SearchTextEntity;
import org.thingsboard.server.dao.util.mapping.JsonStringType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@TypeDef(name = "json", typeClass = JsonStringType.class)
@Table(name = ModelConstants.TENANT_PROFILE_COLUMN_FAMILY_NAME)
public final class TenantProfileEntity extends BaseSqlEntity<TenantProfile> implements SearchTextEntity<TenantProfile> {
@Column(name = ModelConstants.TENANT_PROFILE_NAME_PROPERTY)
private String name;
@Column(name = ModelConstants.TENANT_PROFILE_DESCRIPTION_PROPERTY)
private String description;
@Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
private String searchText;
@Column(name = ModelConstants.TENANT_PROFILE_IS_DEFAULT_PROPERTY)
private boolean isDefault;
@Column(name = ModelConstants.TENANT_PROFILE_ISOLATED_TB_CORE)
private boolean isolatedTbCore;
@Column(name = ModelConstants.TENANT_PROFILE_ISOLATED_TB_RULE_ENGINE)
private boolean isolatedTbRuleEngine;
@Type(type = "json")
@Column(name = ModelConstants.TENANT_PROFILE_PROFILE_DATA_PROPERTY)
private JsonNode profileData;
public TenantProfileEntity() {
super();
}
public TenantProfileEntity(TenantProfile tenantProfile) {
if (tenantProfile.getId() != null) {
this.setUuid(tenantProfile.getId().getId());
}
this.setCreatedTime(tenantProfile.getCreatedTime());
this.name = tenantProfile.getName();
this.description = tenantProfile.getDescription();
this.isDefault = tenantProfile.isDefault();
this.isolatedTbCore = tenantProfile.isIsolatedTbCore();
this.isolatedTbRuleEngine = tenantProfile.isIsolatedTbRuleEngine();
this.profileData = tenantProfile.getProfileData();
}
@Override
public String getSearchTextSource() {
return name;
}
@Override
public void setSearchText(String searchText) {
this.searchText = searchText;
}
public String getSearchText() {
return searchText;
}
@Override
public TenantProfile toData() {
TenantProfile tenantProfile = new TenantProfile(new TenantProfileId(this.getUuid()));
tenantProfile.setCreatedTime(createdTime);
tenantProfile.setName(name);
tenantProfile.setDescription(description);
tenantProfile.setDefault(isDefault);
tenantProfile.setIsolatedTbCore(isolatedTbCore);
tenantProfile.setIsolatedTbRuleEngine(isolatedTbRuleEngine);
tenantProfile.setProfileData(profileData);
return tenantProfile;
}
}

56
dao/src/main/java/org/thingsboard/server/dao/sql/device/DeviceProfileRepository.java

@ -0,0 +1,56 @@
/**
* Copyright © 2016-2020 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.sql.device;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.dao.model.sql.DeviceProfileEntity;
import java.util.UUID;
public interface DeviceProfileRepository extends PagingAndSortingRepository<DeviceProfileEntity, UUID> {
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(d.id, 'DEVICE_PROFILE', d.name) " +
"FROM DeviceProfileEntity d " +
"WHERE d.id = :deviceProfileId")
EntityInfo findDeviceProfileInfoById(@Param("deviceProfileId") UUID deviceProfileId);
@Query("SELECT d FROM DeviceProfileEntity d WHERE " +
"d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<DeviceProfileEntity> findDeviceProfiles(@Param("tenantId") UUID tenantId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(d.id, 'DEVICE_PROFILE', d.name) " +
"FROM DeviceProfileEntity d WHERE " +
"d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<EntityInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId,
@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT d FROM DeviceProfileEntity d " +
"WHERE d.tenantId = :tenantId AND d.isDefault = true")
DeviceProfileEntity findByDefaultTrueAndTenantId(@Param("tenantId") UUID tenantId);
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(d.id, 'DEVICE_PROFILE', d.name) " +
"FROM DeviceProfileEntity d " +
"WHERE d.tenantId = :tenantId AND d.isDefault = true")
EntityInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId);
}

83
dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceProfileDao.java

@ -0,0 +1,83 @@
/**
* Copyright © 2016-2020 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.sql.device;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.device.DeviceProfileDao;
import org.thingsboard.server.dao.model.sql.DeviceProfileEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import java.util.Objects;
import java.util.UUID;
@Component
public class JpaDeviceProfileDao extends JpaAbstractSearchTextDao<DeviceProfileEntity, DeviceProfile> implements DeviceProfileDao {
@Autowired
private DeviceProfileRepository deviceProfileRepository;
@Override
protected Class<DeviceProfileEntity> getEntityClass() {
return DeviceProfileEntity.class;
}
@Override
protected CrudRepository<DeviceProfileEntity, UUID> getCrudRepository() {
return deviceProfileRepository;
}
@Override
public EntityInfo findDeviceProfileInfoById(TenantId tenantId, UUID deviceProfileId) {
return deviceProfileRepository.findDeviceProfileInfoById(deviceProfileId);
}
@Override
public PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(
deviceProfileRepository.findDeviceProfiles(
tenantId.getId(),
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink) {
return DaoUtil.pageToPageData(
deviceProfileRepository.findDeviceProfileInfos(
tenantId.getId(),
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public DeviceProfile findDefaultDeviceProfile(TenantId tenantId) {
return DaoUtil.getData(deviceProfileRepository.findByDefaultTrueAndTenantId(tenantId.getId()));
}
@Override
public EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId) {
return deviceProfileRepository.findDefaultDeviceProfileInfo(tenantId.getId());
}
}

80
dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantProfileDao.java

@ -0,0 +1,80 @@
/**
* Copyright © 2016-2020 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.sql.tenant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.TenantProfileEntity;
import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import org.thingsboard.server.dao.tenant.TenantProfileDao;
import java.util.Objects;
import java.util.UUID;
@Component
public class JpaTenantProfileDao extends JpaAbstractSearchTextDao<TenantProfileEntity, TenantProfile> implements TenantProfileDao {
@Autowired
private TenantProfileRepository tenantProfileRepository;
@Override
protected Class<TenantProfileEntity> getEntityClass() {
return TenantProfileEntity.class;
}
@Override
protected CrudRepository<TenantProfileEntity, UUID> getCrudRepository() {
return tenantProfileRepository;
}
@Override
public EntityInfo findTenantProfileInfoById(TenantId tenantId, UUID tenantProfileId) {
return tenantProfileRepository.findTenantProfileInfoById(tenantProfileId);
}
@Override
public PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink) {
return DaoUtil.toPageData(
tenantProfileRepository.findTenantProfiles(
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink) {
return DaoUtil.pageToPageData(
tenantProfileRepository.findTenantProfileInfos(
Objects.toString(pageLink.getTextSearch(), ""),
DaoUtil.toPageable(pageLink)));
}
@Override
public TenantProfile findDefaultTenantProfile(TenantId tenantId) {
return DaoUtil.getData(tenantProfileRepository.findByDefaultTrue());
}
@Override
public EntityInfo findDefaultTenantProfileInfo(TenantId tenantId) {
return tenantProfileRepository.findDefaultTenantProfileInfo();
}
}

54
dao/src/main/java/org/thingsboard/server/dao/sql/tenant/TenantProfileRepository.java

@ -0,0 +1,54 @@
/**
* Copyright © 2016-2020 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.sql.tenant;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.dao.model.sql.TenantProfileEntity;
import java.util.UUID;
public interface TenantProfileRepository extends PagingAndSortingRepository<TenantProfileEntity, UUID> {
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(t.id, 'TENANT_PROFILE', t.name) " +
"FROM TenantProfileEntity t " +
"WHERE t.id = :tenantProfileId")
EntityInfo findTenantProfileInfoById(@Param("tenantProfileId") UUID tenantProfileId);
@Query("SELECT t FROM TenantProfileEntity t WHERE " +
"LOWER(t.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<TenantProfileEntity> findTenantProfiles(@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(t.id, 'TENANT_PROFILE', t.name) " +
"FROM TenantProfileEntity t " +
"WHERE LOWER(t.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
Page<EntityInfo> findTenantProfileInfos(@Param("textSearch") String textSearch,
Pageable pageable);
@Query("SELECT t FROM TenantProfileEntity t " +
"WHERE t.isDefault = true")
TenantProfileEntity findByDefaultTrue();
@Query("SELECT new org.thingsboard.server.common.data.EntityInfo(t.id, 'TENANT_PROFILE', t.name) " +
"FROM TenantProfileEntity t " +
"WHERE t.isDefault = true")
EntityInfo findDefaultTenantProfileInfo();
}

40
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileDao.java

@ -0,0 +1,40 @@
/**
* Copyright © 2016-2020 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.tenant;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.Dao;
import java.util.UUID;
public interface TenantProfileDao extends Dao<TenantProfile> {
EntityInfo findTenantProfileInfoById(TenantId tenantId, UUID tenantProfileId);
TenantProfile save(TenantId tenantId, TenantProfile tenantProfile);
PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink);
PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink);
TenantProfile findDefaultTenantProfile(TenantId tenantId);
EntityInfo findDefaultTenantProfileInfo(TenantId tenantId);
}

187
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantProfileServiceImpl.java

@ -0,0 +1,187 @@
/**
* Copyright © 2016-2020 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.tenant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.service.DataValidator;
import org.thingsboard.server.dao.service.PaginatedRemover;
import org.thingsboard.server.dao.service.Validator;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import static org.thingsboard.server.dao.service.Validator.validateId;
@Service
@Slf4j
public class TenantProfileServiceImpl extends AbstractEntityService implements TenantProfileService {
private static final String INCORRECT_TENANT_PROFILE_ID = "Incorrect tenantProfileId ";
@Autowired
private TenantProfileDao tenantProfileDao;
@Override
public TenantProfile findTenantProfileById(TenantId tenantId, TenantProfileId tenantProfileId) {
log.trace("Executing findTenantProfileById [{}]", tenantProfileId);
Validator.validateId(tenantProfileId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
return tenantProfileDao.findById(tenantId, tenantProfileId.getId());
}
@Override
public EntityInfo findTenantProfileInfoById(TenantId tenantId, TenantProfileId tenantProfileId) {
log.trace("Executing findTenantProfileInfoById [{}]", tenantProfileId);
Validator.validateId(tenantProfileId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
return tenantProfileDao.findTenantProfileInfoById(tenantId, tenantProfileId.getId());
}
@Override
public TenantProfile saveTenantProfile(TenantId tenantId, TenantProfile tenantProfile) {
log.trace("Executing saveTenantProfile [{}]", tenantProfile);
tenantProfileValidator.validate(tenantProfile, (tenantProfile1) -> TenantId.SYS_TENANT_ID);
TenantProfile savedTenantProfile;
try {
savedTenantProfile = tenantProfileDao.save(tenantId, tenantProfile);
} catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("tenant_profile_name_unq_key")) {
throw new DataValidationException("Tenant profile with such name already exists!");
} else {
throw t;
}
}
return savedTenantProfile;
}
@Override
public void deleteTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
log.trace("Executing deleteTenantProfile [{}]", tenantProfileId);
validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
deleteEntityRelations(tenantId, tenantProfileId);
tenantProfileDao.removeById(tenantId, tenantProfileId.getId());
}
@Override
public PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findTenantProfiles pageLink [{}]", pageLink);
Validator.validatePageLink(pageLink);
return tenantProfileDao.findTenantProfiles(tenantId, pageLink);
}
@Override
public PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink) {
log.trace("Executing findTenantProfileInfos pageLink [{}]", pageLink);
Validator.validatePageLink(pageLink);
return tenantProfileDao.findTenantProfileInfos(tenantId, pageLink);
}
@Override
public TenantProfile findOrCreateDefaultTenantProfile(TenantId tenantId) {
log.trace("Executing findOrCreateDefaultTenantProfile");
TenantProfile defaultTenantProfile = findDefaultTenantProfile(tenantId);
if (defaultTenantProfile == null) {
defaultTenantProfile = new TenantProfile();
defaultTenantProfile.setDefault(true);
defaultTenantProfile.setName("Default");
defaultTenantProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
defaultTenantProfile.setDescription("Default tenant profile");
defaultTenantProfile.setIsolatedTbCore(false);
defaultTenantProfile.setIsolatedTbRuleEngine(false);
defaultTenantProfile = saveTenantProfile(tenantId, defaultTenantProfile);
}
return defaultTenantProfile;
}
@Override
public TenantProfile findDefaultTenantProfile(TenantId tenantId) {
log.trace("Executing findDefaultTenantProfile");
return tenantProfileDao.findDefaultTenantProfile(tenantId);
}
@Override
public EntityInfo findDefaultTenantProfileInfo(TenantId tenantId) {
log.trace("Executing findDefaultTenantProfileInfo");
return tenantProfileDao.findDefaultTenantProfileInfo(tenantId);
}
@Override
public boolean setDefaultTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
log.trace("Executing setDefaultTenantProfile [{}]", tenantProfileId);
validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenantProfileId.getId());
if (!tenantProfile.isDefault()) {
tenantProfile.setDefault(true);
TenantProfile previousDefaultTenantProfile = findDefaultTenantProfile(tenantId);
if (previousDefaultTenantProfile == null) {
tenantProfileDao.save(tenantId, tenantProfile);
return true;
} else if (!previousDefaultTenantProfile.getId().equals(tenantProfile.getId())) {
previousDefaultTenantProfile.setDefault(false);
tenantProfileDao.save(tenantId, previousDefaultTenantProfile);
tenantProfileDao.save(tenantId, tenantProfile);
return true;
}
}
return false;
}
@Override
public void deleteTenantProfiles(TenantId tenantId) {
log.trace("Executing deleteTenantProfiles");
tenantProfilesRemover.removeEntities(tenantId, null);
}
private DataValidator<TenantProfile> tenantProfileValidator =
new DataValidator<TenantProfile>() {
@Override
protected void validateDataImpl(TenantId tenantId, TenantProfile tenantProfile) {
if (StringUtils.isEmpty(tenantProfile.getName())) {
throw new DataValidationException("Tenant profile name should be specified!");
}
if (tenantProfile.isDefault()) {
TenantProfile defaultTenantProfile = findDefaultTenantProfile(tenantId);
if (defaultTenantProfile != null && !defaultTenantProfile.getId().equals(tenantProfile.getId())) {
throw new DataValidationException("Another default tenant profile is present!");
}
}
}
};
private PaginatedRemover<String, TenantProfile> tenantProfilesRemover =
new PaginatedRemover<String, TenantProfile>() {
@Override
protected PageData<TenantProfile> findEntities(TenantId tenantId, String id, PageLink pageLink) {
return tenantProfileDao.findTenantProfiles(tenantId, pageLink);
}
@Override
protected void removeEntity(TenantId tenantId, TenantProfile entity) {
deleteTenantProfile(tenantId, new TenantProfileId(entity.getUuidId()));
}
};
}

27
dao/src/main/java/org/thingsboard/server/dao/tenant/TenantServiceImpl.java

@ -20,14 +20,18 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.asset.AssetService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entity.AbstractEntityService;
import org.thingsboard.server.dao.entityview.EntityViewService;
@ -51,6 +55,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
@Autowired
private TenantDao tenantDao;
@Autowired
private TenantProfileService tenantProfileService;
@Autowired
private UserService userService;
@ -63,6 +70,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
@Autowired
private DeviceService deviceService;
@Autowired
private DeviceProfileService deviceProfileService;
@Autowired
private EntityViewService entityViewService;
@ -93,8 +103,16 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
public Tenant saveTenant(Tenant tenant) {
log.trace("Executing saveTenant [{}]", tenant);
tenant.setRegion(DEFAULT_TENANT_REGION);
if (tenant.getTenantProfileId() == null) {
TenantProfile tenantProfile = this.tenantProfileService.findOrCreateDefaultTenantProfile(TenantId.SYS_TENANT_ID);
tenant.setTenantProfileId(tenantProfile.getId());
}
tenantValidator.validate(tenant, Tenant::getId);
return tenantDao.save(tenant.getId(), tenant);
Tenant savedTenant = tenantDao.save(tenant.getId(), tenant);
if (tenant.getId() == null) {
deviceProfileService.createDefaultDeviceProfile(savedTenant.getId());
}
return savedTenant;
}
@Override
@ -107,6 +125,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
entityViewService.deleteEntityViewsByTenantId(tenantId);
assetService.deleteAssetsByTenantId(tenantId);
deviceService.deleteDevicesByTenantId(tenantId);
deviceProfileService.deleteDeviceProfilesByTenantId(tenantId);
userService.deleteTenantAdmins(tenantId);
ruleChainService.deleteRuleChainsByTenantId(tenantId);
tenantDao.removeById(tenantId, tenantId.getId());
@ -143,11 +162,13 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
Tenant old = tenantDao.findById(TenantId.SYS_TENANT_ID, tenantId.getId());
if (old == null) {
throw new DataValidationException("Can't update non existing tenant!");
} else if (old.isIsolatedTbRuleEngine() != tenant.isIsolatedTbRuleEngine()) {
}
// TODO: Move validation to tenant profile
/* else if (old.isIsolatedTbRuleEngine() != tenant.isIsolatedTbRuleEngine()) {
throw new DataValidationException("Can't update isolatedTbRuleEngine property!");
} else if (old.isIsolatedTbCore() != tenant.isIsolatedTbCore()) {
throw new DataValidationException("Can't update isolatedTbCore property!");
}
} */
}
};

28
dao/src/main/resources/sql/schema-entities-hsql.sql

@ -127,6 +127,7 @@ CREATE TABLE IF NOT EXISTS device (
created_time bigint NOT NULL,
additional_info varchar,
customer_id uuid,
device_profile_id uuid NOT NULL,
type varchar(255),
name varchar(255),
label varchar(255),
@ -135,6 +136,19 @@ CREATE TABLE IF NOT EXISTS device (
CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name)
);
CREATE TABLE IF NOT EXISTS device_profile (
id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY,
created_time bigint NOT NULL,
name varchar(255),
profile_data varchar,
description varchar,
search_text varchar(255),
is_default boolean,
tenant_id uuid,
default_rule_chain_id uuid,
CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name)
);
CREATE TABLE IF NOT EXISTS device_credentials (
id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY,
created_time bigint NOT NULL,
@ -187,6 +201,7 @@ CREATE TABLE IF NOT EXISTS tenant (
id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY,
created_time bigint NOT NULL,
additional_info varchar,
tenant_profile_id uuid NOT NULL,
address varchar,
address2 varchar,
city varchar(255),
@ -202,6 +217,19 @@ CREATE TABLE IF NOT EXISTS tenant (
isolated_tb_rule_engine boolean
);
CREATE TABLE IF NOT EXISTS tenant_profile (
id uuid NOT NULL CONSTRAINT tenant_profile_pkey PRIMARY KEY,
created_time bigint NOT NULL,
name varchar(255),
profile_data varchar,
description varchar,
search_text varchar(255),
is_default boolean,
isolated_tb_core boolean,
isolated_tb_rule_engine boolean,
CONSTRAINT tenant_profile_name_unq_key UNIQUE (name)
);
CREATE TABLE IF NOT EXISTS user_credentials (
id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY,
created_time bigint NOT NULL,

28
dao/src/main/resources/sql/schema-entities.sql

@ -144,6 +144,7 @@ CREATE TABLE IF NOT EXISTS device (
created_time bigint NOT NULL,
additional_info varchar,
customer_id uuid,
device_profile_id uuid NOT NULL,
type varchar(255),
name varchar(255),
label varchar(255),
@ -152,6 +153,19 @@ CREATE TABLE IF NOT EXISTS device (
CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name)
);
CREATE TABLE IF NOT EXISTS device_profile (
id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY,
created_time bigint NOT NULL,
name varchar(255),
profile_data varchar,
description varchar,
search_text varchar(255),
is_default boolean,
tenant_id uuid,
default_rule_chain_id uuid,
CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name)
);
CREATE TABLE IF NOT EXISTS device_credentials (
id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY,
created_time bigint NOT NULL,
@ -211,6 +225,7 @@ CREATE TABLE IF NOT EXISTS tenant (
id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY,
created_time bigint NOT NULL,
additional_info varchar,
tenant_profile_id uuid NOT NULL,
address varchar,
address2 varchar,
city varchar(255),
@ -226,6 +241,19 @@ CREATE TABLE IF NOT EXISTS tenant (
isolated_tb_rule_engine boolean
);
CREATE TABLE IF NOT EXISTS tenant_profile (
id uuid NOT NULL CONSTRAINT tenant_profile_pkey PRIMARY KEY,
created_time bigint NOT NULL,
name varchar(255),
profile_data varchar,
description varchar,
search_text varchar(255),
is_default boolean,
isolated_tb_core boolean,
isolated_tb_rule_engine boolean,
CONSTRAINT tenant_profile_name_unq_key UNIQUE (name)
);
CREATE TABLE IF NOT EXISTS user_credentials (
id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY,
created_time bigint NOT NULL,

11
dao/src/test/java/org/thingsboard/server/dao/service/AbstractServiceTest.java

@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.BaseData;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.HasId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.dao.alarm.AlarmService;
@ -41,6 +42,7 @@ import org.thingsboard.server.dao.component.ComponentDescriptorService;
import org.thingsboard.server.dao.customer.CustomerService;
import org.thingsboard.server.dao.dashboard.DashboardService;
import org.thingsboard.server.dao.device.DeviceCredentialsService;
import org.thingsboard.server.dao.device.DeviceProfileService;
import org.thingsboard.server.dao.device.DeviceService;
import org.thingsboard.server.dao.entity.EntityService;
import org.thingsboard.server.dao.entityview.EntityViewService;
@ -48,6 +50,7 @@ import org.thingsboard.server.dao.event.EventService;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService;
import org.thingsboard.server.dao.timeseries.TimeseriesService;
import org.thingsboard.server.dao.user.UserService;
@ -125,7 +128,13 @@ public abstract class AbstractServiceTest {
@Autowired
private ComponentDescriptorService componentDescriptorService;
class IdComparator<D extends BaseData<? extends UUIDBased>> implements Comparator<D> {
@Autowired
protected TenantProfileService tenantProfileService;
@Autowired
protected DeviceProfileService deviceProfileService;
class IdComparator<D extends HasId> implements Comparator<D> {
@Override
public int compare(D o1, D o2) {
return o1.getId().getId().compareTo(o2.getId().getId());

262
dao/src/test/java/org/thingsboard/server/dao/service/BaseDeviceProfileServiceTest.java

@ -0,0 +1,262 @@
/**
* Copyright © 2016-2020 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.service;
import com.datastax.oss.driver.api.core.uuid.Uuids;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.thingsboard.server.common.data.DeviceProfile;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
private IdComparator<DeviceProfile> idComparator = new IdComparator<>();
private IdComparator<EntityInfo> deviceProfileInfoIdComparator = new IdComparator<>();
private TenantId tenantId;
@Before
public void before() {
Tenant tenant = new Tenant();
tenant.setTitle("My tenant");
Tenant savedTenant = tenantService.saveTenant(tenant);
Assert.assertNotNull(savedTenant);
tenantId = savedTenant.getId();
}
@After
public void after() {
tenantService.deleteTenant(tenantId);
}
@Test
public void testSaveDeviceProfile() {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
Assert.assertNotNull(savedDeviceProfile);
Assert.assertNotNull(savedDeviceProfile.getId());
Assert.assertTrue(savedDeviceProfile.getCreatedTime() > 0);
Assert.assertEquals(deviceProfile.getName(), savedDeviceProfile.getName());
Assert.assertEquals(deviceProfile.getDescription(), savedDeviceProfile.getDescription());
Assert.assertEquals(deviceProfile.getProfileData(), savedDeviceProfile.getProfileData());
Assert.assertEquals(deviceProfile.isDefault(), savedDeviceProfile.isDefault());
Assert.assertEquals(deviceProfile.getDefaultRuleChainId(), savedDeviceProfile.getDefaultRuleChainId());
savedDeviceProfile.setName("New device profile");
deviceProfileService.saveDeviceProfile(savedDeviceProfile);
DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
Assert.assertEquals(foundDeviceProfile.getName(), savedDeviceProfile.getName());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
}
@Test
public void testFindDeviceProfileById() {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
Assert.assertNotNull(foundDeviceProfile);
Assert.assertEquals(savedDeviceProfile, foundDeviceProfile);
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
}
@Test
public void testFindDeviceProfileInfoById() {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
EntityInfo foundDeviceProfileInfo = deviceProfileService.findDeviceProfileInfoById(tenantId, savedDeviceProfile.getId());
Assert.assertNotNull(foundDeviceProfileInfo);
Assert.assertEquals(savedDeviceProfile.getId(), foundDeviceProfileInfo.getId());
Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfileInfo.getName());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
}
@Test
public void testFindDefaultDeviceProfile() {
DeviceProfile foundDefaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
Assert.assertNotNull(foundDefaultDeviceProfile);
Assert.assertNotNull(foundDefaultDeviceProfile.getId());
Assert.assertNotNull(foundDefaultDeviceProfile.getName());
}
@Test
public void testFindDefaultDeviceProfileInfo() {
EntityInfo foundDefaultDeviceProfileInfo = deviceProfileService.findDefaultDeviceProfileInfo(tenantId);
Assert.assertNotNull(foundDefaultDeviceProfileInfo.getId());
Assert.assertNotNull(foundDefaultDeviceProfileInfo.getName());
Assert.assertNotNull(foundDefaultDeviceProfileInfo);
}
@Test
public void testSetDefaultDeviceProfile() {
DeviceProfile deviceProfile1 = this.createDeviceProfile("Device Profile 1");
DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile 2");
DeviceProfile savedDeviceProfile1 = deviceProfileService.saveDeviceProfile(deviceProfile1);
DeviceProfile savedDeviceProfile2 = deviceProfileService.saveDeviceProfile(deviceProfile2);
boolean result = deviceProfileService.setDefaultDeviceProfile(tenantId, savedDeviceProfile1.getId());
Assert.assertTrue(result);
DeviceProfile defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
Assert.assertNotNull(defaultDeviceProfile);
Assert.assertEquals(savedDeviceProfile1.getId(), defaultDeviceProfile.getId());
result = deviceProfileService.setDefaultDeviceProfile(tenantId, savedDeviceProfile2.getId());
Assert.assertTrue(result);
defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
Assert.assertNotNull(defaultDeviceProfile);
Assert.assertEquals(savedDeviceProfile2.getId(), defaultDeviceProfile.getId());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile1.getId());
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile2.getId());
}
@Test(expected = DataValidationException.class)
public void testSaveDeviceProfileWithEmptyName() {
DeviceProfile deviceProfile = new DeviceProfile();
deviceProfile.setTenantId(tenantId);
deviceProfileService.saveDeviceProfile(deviceProfile);
}
@Test(expected = DataValidationException.class)
public void testSaveDeviceProfileWithSameName() {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
deviceProfileService.saveDeviceProfile(deviceProfile);
DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile");
deviceProfileService.saveDeviceProfile(deviceProfile2);
}
@Test
public void testDeleteDeviceProfile() {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
Assert.assertNull(foundDeviceProfile);
}
@Test
public void testFindDeviceProfiles() {
List<DeviceProfile> deviceProfiles = new ArrayList<>();
PageLink pageLink = new PageLink(17);
PageData<DeviceProfile> pageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(1, pageData.getTotalElements());
deviceProfiles.addAll(pageData.getData());
for (int i=0;i<28;i++) {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i);
deviceProfiles.add(deviceProfileService.saveDeviceProfile(deviceProfile));
}
List<DeviceProfile> loadedDeviceProfiles = new ArrayList<>();
pageLink = new PageLink(17);
do {
pageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
loadedDeviceProfiles.addAll(pageData.getData());
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} while (pageData.hasNext());
Collections.sort(deviceProfiles, idComparator);
Collections.sort(loadedDeviceProfiles, idComparator);
Assert.assertEquals(deviceProfiles, loadedDeviceProfiles);
for (DeviceProfile deviceProfile : loadedDeviceProfiles) {
if (!deviceProfile.isDefault()) {
deviceProfileService.deleteDeviceProfile(tenantId, deviceProfile.getId());
}
}
pageLink = new PageLink(17);
pageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(1, pageData.getTotalElements());
}
@Test
public void testFindDeviceProfileInfos() {
List<DeviceProfile> deviceProfiles = new ArrayList<>();
PageLink pageLink = new PageLink(17);
PageData<DeviceProfile> deviceProfilePageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
Assert.assertFalse(deviceProfilePageData.hasNext());
Assert.assertEquals(1, deviceProfilePageData.getTotalElements());
deviceProfiles.addAll(deviceProfilePageData.getData());
for (int i=0;i<28;i++) {
DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i);
deviceProfiles.add(deviceProfileService.saveDeviceProfile(deviceProfile));
}
List<EntityInfo> loadedDeviceProfileInfos = new ArrayList<>();
pageLink = new PageLink(17);
PageData<EntityInfo> pageData;
do {
pageData = deviceProfileService.findDeviceProfileInfos(tenantId, pageLink);
loadedDeviceProfileInfos.addAll(pageData.getData());
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} while (pageData.hasNext());
Collections.sort(deviceProfiles, idComparator);
Collections.sort(loadedDeviceProfileInfos, deviceProfileInfoIdComparator);
List<EntityInfo> deviceProfileInfos = deviceProfiles.stream().map(deviceProfile -> new EntityInfo(deviceProfile.getId(),
deviceProfile.getName())).collect(Collectors.toList());
Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos);
for (DeviceProfile deviceProfile : deviceProfiles) {
if (!deviceProfile.isDefault()) {
deviceProfileService.deleteDeviceProfile(tenantId, deviceProfile.getId());
}
}
pageLink = new PageLink(17);
pageData = deviceProfileService.findDeviceProfileInfos(tenantId, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertEquals(1, pageData.getTotalElements());
}
private DeviceProfile createDeviceProfile(String name) {
DeviceProfile deviceProfile = new DeviceProfile();
deviceProfile.setTenantId(tenantId);
deviceProfile.setName(name);
deviceProfile.setDescription(name + " Test");
deviceProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
deviceProfile.setDefault(false);
deviceProfile.setDefaultRuleChainId(new RuleChainId(Uuids.timeBased()));
return deviceProfile;
}
}

248
dao/src/test/java/org/thingsboard/server/dao/service/BaseTenantProfileServiceTest.java

@ -0,0 +1,248 @@
/**
* Copyright © 2016-2020 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.service;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import org.thingsboard.server.common.data.EntityInfo;
import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.TenantProfileId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.util.mapping.JacksonUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class BaseTenantProfileServiceTest extends AbstractServiceTest {
private IdComparator<TenantProfile> idComparator = new IdComparator<>();
private IdComparator<EntityInfo> tenantProfileInfoIdComparator = new IdComparator<>();
@After
public void after() {
tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
}
@Test
public void testSaveTenantProfile() {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
Assert.assertNotNull(savedTenantProfile);
Assert.assertNotNull(savedTenantProfile.getId());
Assert.assertTrue(savedTenantProfile.getCreatedTime() > 0);
Assert.assertEquals(tenantProfile.getName(), savedTenantProfile.getName());
Assert.assertEquals(tenantProfile.getDescription(), savedTenantProfile.getDescription());
Assert.assertEquals(tenantProfile.getProfileData(), savedTenantProfile.getProfileData());
Assert.assertEquals(tenantProfile.isDefault(), savedTenantProfile.isDefault());
Assert.assertEquals(tenantProfile.isIsolatedTbCore(), savedTenantProfile.isIsolatedTbCore());
Assert.assertEquals(tenantProfile.isIsolatedTbRuleEngine(), savedTenantProfile.isIsolatedTbRuleEngine());
savedTenantProfile.setName("New tenant profile");
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile);
TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
Assert.assertEquals(foundTenantProfile.getName(), savedTenantProfile.getName());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
}
@Test
public void testFindTenantProfileById() {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
Assert.assertNotNull(foundTenantProfile);
Assert.assertEquals(savedTenantProfile, foundTenantProfile);
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
}
@Test
public void testFindTenantProfileInfoById() {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
EntityInfo foundTenantProfileInfo = tenantProfileService.findTenantProfileInfoById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
Assert.assertNotNull(foundTenantProfileInfo);
Assert.assertEquals(savedTenantProfile.getId(), foundTenantProfileInfo.getId());
Assert.assertEquals(savedTenantProfile.getName(), foundTenantProfileInfo.getName());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
}
@Test
public void testFindDefaultTenantProfile() {
TenantProfile tenantProfile = this.createTenantProfile("Default Tenant Profile");
tenantProfile.setDefault(true);
TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
TenantProfile foundDefaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
Assert.assertNotNull(foundDefaultTenantProfile);
Assert.assertEquals(savedTenantProfile, foundDefaultTenantProfile);
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
}
@Test
public void testFindDefaultTenantProfileInfo() {
TenantProfile tenantProfile = this.createTenantProfile("Default Tenant Profile");
tenantProfile.setDefault(true);
TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
EntityInfo foundDefaultTenantProfileInfo = tenantProfileService.findDefaultTenantProfileInfo(TenantId.SYS_TENANT_ID);
Assert.assertNotNull(foundDefaultTenantProfileInfo);
Assert.assertEquals(savedTenantProfile.getId(), foundDefaultTenantProfileInfo.getId());
Assert.assertEquals(savedTenantProfile.getName(), foundDefaultTenantProfileInfo.getName());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
}
@Test
public void testSetDefaultTenantProfile() {
TenantProfile tenantProfile1 = this.createTenantProfile("Tenant Profile 1");
TenantProfile tenantProfile2 = this.createTenantProfile("Tenant Profile 2");
TenantProfile savedTenantProfile1 = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile1);
TenantProfile savedTenantProfile2 = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile2);
boolean result = tenantProfileService.setDefaultTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile1.getId());
Assert.assertTrue(result);
TenantProfile defaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
Assert.assertNotNull(defaultTenantProfile);
Assert.assertEquals(savedTenantProfile1.getId(), defaultTenantProfile.getId());
result = tenantProfileService.setDefaultTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile2.getId());
Assert.assertTrue(result);
defaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
Assert.assertNotNull(defaultTenantProfile);
Assert.assertEquals(savedTenantProfile2.getId(), defaultTenantProfile.getId());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile1.getId());
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile2.getId());
}
@Test(expected = DataValidationException.class)
public void testSaveTenantProfileWithEmptyName() {
TenantProfile tenantProfile = new TenantProfile();
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
}
@Test(expected = DataValidationException.class)
public void testSaveTenantProfileWithSameName() {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
TenantProfile tenantProfile2 = this.createTenantProfile("Tenant Profile");
tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile2);
}
@Test
public void testDeleteTenantProfile() {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
Assert.assertNull(foundTenantProfile);
}
@Test
public void testFindTenantProfiles() {
List<TenantProfile> tenantProfiles = new ArrayList<>();
PageLink pageLink = new PageLink(17);
PageData<TenantProfile> pageData = tenantProfileService.findTenantProfiles(TenantId.SYS_TENANT_ID, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty());
tenantProfiles.addAll(pageData.getData());
for (int i=0;i<28;i++) {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile"+i);
tenantProfiles.add(tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile));
}
List<TenantProfile> loadedTenantProfiles = new ArrayList<>();
pageLink = new PageLink(17);
do {
pageData = tenantProfileService.findTenantProfiles(TenantId.SYS_TENANT_ID, pageLink);
loadedTenantProfiles.addAll(pageData.getData());
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} while (pageData.hasNext());
Collections.sort(tenantProfiles, idComparator);
Collections.sort(loadedTenantProfiles, idComparator);
Assert.assertEquals(tenantProfiles, loadedTenantProfiles);
for (TenantProfile tenantProfile : loadedTenantProfiles) {
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile.getId());
}
pageLink = new PageLink(17);
pageData = tenantProfileService.findTenantProfiles(TenantId.SYS_TENANT_ID, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty());
}
@Test
public void testFindTenantProfileInfos() {
List<TenantProfile> tenantProfiles = new ArrayList<>();
for (int i=0;i<28;i++) {
TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile"+i);
tenantProfiles.add(tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile));
}
List<EntityInfo> loadedTenantProfileInfos = new ArrayList<>();
PageLink pageLink = new PageLink(17);
PageData<EntityInfo> pageData;
do {
pageData = tenantProfileService.findTenantProfileInfos(TenantId.SYS_TENANT_ID, pageLink);
loadedTenantProfileInfos.addAll(pageData.getData());
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} while (pageData.hasNext());
Collections.sort(tenantProfiles, idComparator);
Collections.sort(loadedTenantProfileInfos, tenantProfileInfoIdComparator);
List<EntityInfo> tenantProfileInfos = tenantProfiles.stream().map(tenantProfile -> new EntityInfo(tenantProfile.getId(),
tenantProfile.getName())).collect(Collectors.toList());
Assert.assertEquals(tenantProfileInfos, loadedTenantProfileInfos);
for (EntityInfo tenantProfile : loadedTenantProfileInfos) {
tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, new TenantProfileId(tenantProfile.getId().getId()));
}
pageLink = new PageLink(17);
pageData = tenantProfileService.findTenantProfileInfos(TenantId.SYS_TENANT_ID, pageLink);
Assert.assertFalse(pageData.hasNext());
Assert.assertTrue(pageData.getData().isEmpty());
}
private TenantProfile createTenantProfile(String name) {
TenantProfile tenantProfile = new TenantProfile();
tenantProfile.setName(name);
tenantProfile.setDescription(name + " Test");
tenantProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
tenantProfile.setDefault(false);
tenantProfile.setIsolatedTbCore(false);
tenantProfile.setIsolatedTbRuleEngine(false);
return tenantProfile;
}
}

23
dao/src/test/java/org/thingsboard/server/dao/service/sql/DeviceProfileServiceSqlTest.java

@ -0,0 +1,23 @@
/**
* Copyright © 2016-2020 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.service.sql;
import org.thingsboard.server.dao.service.BaseDeviceProfileServiceTest;
import org.thingsboard.server.dao.service.DaoSqlTest;
@DaoSqlTest
public class DeviceProfileServiceSqlTest extends BaseDeviceProfileServiceTest {
}

23
dao/src/test/java/org/thingsboard/server/dao/service/sql/TenantProfileServiceSqlTest.java

@ -0,0 +1,23 @@
/**
* Copyright © 2016-2020 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.service.sql;
import org.thingsboard.server.dao.service.BaseTenantProfileServiceTest;
import org.thingsboard.server.dao.service.DaoSqlTest;
@DaoSqlTest
public class TenantProfileServiceSqlTest extends BaseTenantProfileServiceTest {
}

2
dao/src/test/resources/sql/hsql/drop-all-tables.sql

@ -20,4 +20,6 @@ DROP TABLE IF EXISTS widgets_bundle;
DROP TABLE IF EXISTS rule_node;
DROP TABLE IF EXISTS rule_chain;
DROP TABLE IF EXISTS entity_view;
DROP TABLE IF EXISTS device_profile;
DROP TABLE IF EXISTS tenant_profile;
DROP FUNCTION IF EXISTS to_uuid;

4
dao/src/test/resources/sql/psql/drop-all-tables.sql

@ -21,4 +21,6 @@ DROP TABLE IF EXISTS widgets_bundle;
DROP TABLE IF EXISTS rule_node;
DROP TABLE IF EXISTS rule_chain;
DROP TABLE IF EXISTS entity_view;
DROP TABLE IF EXISTS tb_schema_settings;
DROP TABLE IF EXISTS device_profile;
DROP TABLE IF EXISTS tenant_profile;
DROP TABLE IF EXISTS tb_schema_settings;

4
dao/src/test/resources/sql/timescale/drop-all-tables.sql

@ -21,4 +21,6 @@ DROP TABLE IF EXISTS widgets_bundle;
DROP TABLE IF EXISTS rule_node;
DROP TABLE IF EXISTS rule_chain;
DROP TABLE IF EXISTS entity_view;
DROP TABLE IF EXISTS tb_schema_settings;
DROP TABLE IF EXISTS device_profile;
DROP TABLE IF EXISTS tenant_profile;
DROP TABLE IF EXISTS tb_schema_settings;

Loading…
Cancel
Save