Commit 3ddf14668e2692241e408e0f05a4e131c585b76b

Authored by Igor Kulikov
1 parent 7d7a5062

Tenant and Device profiles DAO layer

Showing 52 changed files with 2242 additions and 50 deletions
  1 +--
  2 +-- Copyright © 2016-2020 The Thingsboard Authors
  3 +--
  4 +-- Licensed under the Apache License, Version 2.0 (the "License");
  5 +-- you may not use this file except in compliance with the License.
  6 +-- You may obtain a copy of the License at
  7 +--
  8 +-- http://www.apache.org/licenses/LICENSE-2.0
  9 +--
  10 +-- Unless required by applicable law or agreed to in writing, software
  11 +-- distributed under the License is distributed on an "AS IS" BASIS,
  12 +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +-- See the License for the specific language governing permissions and
  14 +-- limitations under the License.
  15 +--
  16 +
  17 +ALTER TABLE device ADD COLUMN device_profile_id uuid;
  18 +ALTER TABLE tenant ADD COLUMN tenant_profile_id uuid;
  19 +
  20 +CREATE TABLE IF NOT EXISTS device_profile (
  21 + id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY,
  22 + created_time bigint NOT NULL,
  23 + name varchar(255),
  24 + profile_data varchar,
  25 + description varchar,
  26 + search_text varchar(255),
  27 + default boolean,
  28 + tenant_id uuid,
  29 + default_rule_chain_id uuid
  30 +);
  31 +
  32 +CREATE TABLE IF NOT EXISTS tenant_profile (
  33 + id uuid NOT NULL CONSTRAINT tenant_profile_pkey PRIMARY KEY,
  34 + created_time bigint NOT NULL,
  35 + name varchar(255),
  36 + profile_data varchar,
  37 + description varchar,
  38 + search_text varchar(255),
  39 + default boolean,
  40 + isolated_tb_core boolean,
  41 + isolated_tb_rule_engine boolean
  42 +);
@@ -58,6 +58,7 @@ import org.thingsboard.server.dao.event.EventService; @@ -58,6 +58,7 @@ import org.thingsboard.server.dao.event.EventService;
58 import org.thingsboard.server.dao.nosql.CassandraBufferedRateExecutor; 58 import org.thingsboard.server.dao.nosql.CassandraBufferedRateExecutor;
59 import org.thingsboard.server.dao.relation.RelationService; 59 import org.thingsboard.server.dao.relation.RelationService;
60 import org.thingsboard.server.dao.rule.RuleChainService; 60 import org.thingsboard.server.dao.rule.RuleChainService;
  61 +import org.thingsboard.server.dao.tenant.TenantProfileService;
61 import org.thingsboard.server.dao.tenant.TenantService; 62 import org.thingsboard.server.dao.tenant.TenantService;
62 import org.thingsboard.server.dao.timeseries.TimeseriesService; 63 import org.thingsboard.server.dao.timeseries.TimeseriesService;
63 import org.thingsboard.server.dao.user.UserService; 64 import org.thingsboard.server.dao.user.UserService;
@@ -139,6 +140,10 @@ public class ActorSystemContext { @@ -139,6 +140,10 @@ public class ActorSystemContext {
139 140
140 @Autowired 141 @Autowired
141 @Getter 142 @Getter
  143 + private TenantProfileService tenantProfileService;
  144 +
  145 + @Autowired
  146 + @Getter
142 private CustomerService customerService; 147 private CustomerService customerService;
143 148
144 @Autowired 149 @Autowired
@@ -27,6 +27,7 @@ import org.thingsboard.server.actors.service.DefaultActorService; @@ -27,6 +27,7 @@ import org.thingsboard.server.actors.service.DefaultActorService;
27 import org.thingsboard.server.actors.tenant.TenantActor; 27 import org.thingsboard.server.actors.tenant.TenantActor;
28 import org.thingsboard.server.common.data.EntityType; 28 import org.thingsboard.server.common.data.EntityType;
29 import org.thingsboard.server.common.data.Tenant; 29 import org.thingsboard.server.common.data.Tenant;
  30 +import org.thingsboard.server.common.data.TenantProfile;
30 import org.thingsboard.server.common.data.id.EntityId; 31 import org.thingsboard.server.common.data.id.EntityId;
31 import org.thingsboard.server.common.data.id.TenantId; 32 import org.thingsboard.server.common.data.id.TenantId;
32 import org.thingsboard.server.common.data.page.PageDataIterable; 33 import org.thingsboard.server.common.data.page.PageDataIterable;
@@ -116,7 +117,9 @@ public class AppActor extends ContextAwareActor { @@ -116,7 +117,9 @@ public class AppActor extends ContextAwareActor {
116 boolean isRuleEngine = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE); 117 boolean isRuleEngine = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE);
117 boolean isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE); 118 boolean isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE);
118 for (Tenant tenant : tenantIterator) { 119 for (Tenant tenant : tenantIterator) {
119 - if (isCore || (isRuleEngine && !tenant.isIsolatedTbRuleEngine())) { 120 + // TODO: Tenant Profile from cache
  121 + TenantProfile tenantProfile = systemContext.getTenantProfileService().findTenantProfileById(TenantId.SYS_TENANT_ID, tenant.getTenantProfileId());
  122 + if (isCore || (isRuleEngine && !tenantProfile.isIsolatedTbRuleEngine())) {
120 log.debug("[{}] Creating tenant actor", tenant.getId()); 123 log.debug("[{}] Creating tenant actor", tenant.getId());
121 getOrCreateTenantActor(tenant.getId()); 124 getOrCreateTenantActor(tenant.getId());
122 log.debug("[{}] Tenant actor created.", tenant.getId()); 125 log.debug("[{}] Tenant actor created.", tenant.getId());
@@ -31,6 +31,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator; @@ -31,6 +31,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator;
31 import org.thingsboard.server.actors.service.DefaultActorService; 31 import org.thingsboard.server.actors.service.DefaultActorService;
32 import org.thingsboard.server.common.data.EntityType; 32 import org.thingsboard.server.common.data.EntityType;
33 import org.thingsboard.server.common.data.Tenant; 33 import org.thingsboard.server.common.data.Tenant;
  34 +import org.thingsboard.server.common.data.TenantProfile;
34 import org.thingsboard.server.common.data.id.DeviceId; 35 import org.thingsboard.server.common.data.id.DeviceId;
35 import org.thingsboard.server.common.data.id.EntityId; 36 import org.thingsboard.server.common.data.id.EntityId;
36 import org.thingsboard.server.common.data.id.RuleChainId; 37 import org.thingsboard.server.common.data.id.RuleChainId;
@@ -75,12 +76,16 @@ public class TenantActor extends RuleChainManagerActor { @@ -75,12 +76,16 @@ public class TenantActor extends RuleChainManagerActor {
75 // This Service may be started for specific tenant only. 76 // This Service may be started for specific tenant only.
76 Optional<TenantId> isolatedTenantId = systemContext.getServiceInfoProvider().getIsolatedTenant(); 77 Optional<TenantId> isolatedTenantId = systemContext.getServiceInfoProvider().getIsolatedTenant();
77 78
  79 + // TODO: Tenant Profile from cache
  80 +
  81 + TenantProfile tenantProfile = systemContext.getTenantProfileService().findTenantProfileById(tenantId, tenant.getTenantProfileId());
  82 +
78 isRuleEngineForCurrentTenant = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE); 83 isRuleEngineForCurrentTenant = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE);
79 isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE); 84 isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE);
80 85
81 if (isRuleEngineForCurrentTenant) { 86 if (isRuleEngineForCurrentTenant) {
82 try { 87 try {
83 - if (isolatedTenantId.map(id -> id.equals(tenantId)).orElseGet(() -> !tenant.isIsolatedTbRuleEngine())) { 88 + if (isolatedTenantId.map(id -> id.equals(tenantId)).orElseGet(() -> !tenantProfile.isIsolatedTbRuleEngine())) {
84 log.info("[{}] Going to init rule chains", tenantId); 89 log.info("[{}] Going to init rule chains", tenantId);
85 initRuleChains(); 90 initRuleChains();
86 } else { 91 } else {
@@ -175,6 +175,9 @@ public class ThingsboardInstallService { @@ -175,6 +175,9 @@ public class ThingsboardInstallService {
175 case "3.1.0": 175 case "3.1.0":
176 log.info("Upgrading ThingsBoard from version 3.1.0 to 3.1.1 ..."); 176 log.info("Upgrading ThingsBoard from version 3.1.0 to 3.1.1 ...");
177 databaseEntitiesUpgradeService.upgradeDatabase("3.1.0"); 177 databaseEntitiesUpgradeService.upgradeDatabase("3.1.0");
  178 + case "3.1.1":
  179 + log.info("Upgrading ThingsBoard from version 3.1.1 to 3.2.0 ...");
  180 + databaseEntitiesUpgradeService.upgradeDatabase("3.1.1");
178 log.info("Updating system data..."); 181 log.info("Updating system data...");
179 systemDataLoaderService.updateSystemWidgets(); 182 systemDataLoaderService.updateSystemWidgets();
180 break; 183 break;
@@ -206,6 +209,7 @@ public class ThingsboardInstallService { @@ -206,6 +209,7 @@ public class ThingsboardInstallService {
206 componentDiscoveryService.discoverComponents(); 209 componentDiscoveryService.discoverComponents();
207 210
208 systemDataLoaderService.createSysAdmin(); 211 systemDataLoaderService.createSysAdmin();
  212 + systemDataLoaderService.createDefaultTenantProfile();
209 systemDataLoaderService.createAdminSettings(); 213 systemDataLoaderService.createAdminSettings();
210 systemDataLoaderService.loadSystemWidgets(); 214 systemDataLoaderService.loadSystemWidgets();
211 // systemDataLoaderService.loadSystemPlugins(); 215 // systemDataLoaderService.loadSystemPlugins();
@@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.Customer; @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.Customer;
28 import org.thingsboard.server.common.data.DataConstants; 28 import org.thingsboard.server.common.data.DataConstants;
29 import org.thingsboard.server.common.data.Device; 29 import org.thingsboard.server.common.data.Device;
30 import org.thingsboard.server.common.data.Tenant; 30 import org.thingsboard.server.common.data.Tenant;
  31 +import org.thingsboard.server.common.data.TenantProfile;
31 import org.thingsboard.server.common.data.User; 32 import org.thingsboard.server.common.data.User;
32 import org.thingsboard.server.common.data.asset.Asset; 33 import org.thingsboard.server.common.data.asset.Asset;
33 import org.thingsboard.server.common.data.id.CustomerId; 34 import org.thingsboard.server.common.data.id.CustomerId;
@@ -49,6 +50,7 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService; @@ -49,6 +50,7 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService;
49 import org.thingsboard.server.dao.device.DeviceService; 50 import org.thingsboard.server.dao.device.DeviceService;
50 import org.thingsboard.server.dao.relation.RelationService; 51 import org.thingsboard.server.dao.relation.RelationService;
51 import org.thingsboard.server.dao.settings.AdminSettingsService; 52 import org.thingsboard.server.dao.settings.AdminSettingsService;
  53 +import org.thingsboard.server.dao.tenant.TenantProfileService;
52 import org.thingsboard.server.dao.tenant.TenantService; 54 import org.thingsboard.server.dao.tenant.TenantService;
53 import org.thingsboard.server.dao.user.UserService; 55 import org.thingsboard.server.dao.user.UserService;
54 import org.thingsboard.server.dao.widget.WidgetsBundleService; 56 import org.thingsboard.server.dao.widget.WidgetsBundleService;
@@ -83,6 +85,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -83,6 +85,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
83 private TenantService tenantService; 85 private TenantService tenantService;
84 86
85 @Autowired 87 @Autowired
  88 + private TenantProfileService tenantProfileService;
  89 +
  90 + @Autowired
86 private CustomerService customerService; 91 private CustomerService customerService;
87 92
88 @Autowired 93 @Autowired
@@ -111,6 +116,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService { @@ -111,6 +116,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
111 } 116 }
112 117
113 @Override 118 @Override
  119 + public void createDefaultTenantProfile() throws Exception {
  120 + tenantProfileService.findOrCreateDefaultTenantProfile(TenantId.SYS_TENANT_ID);
  121 + }
  122 +
  123 + @Override
114 public void createAdminSettings() throws Exception { 124 public void createAdminSettings() throws Exception {
115 AdminSettings generalSettings = new AdminSettings(); 125 AdminSettings generalSettings = new AdminSettings();
116 generalSettings.setKey("general"); 126 generalSettings.setKey("general");
@@ -303,6 +303,14 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService @@ -303,6 +303,14 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
303 log.info("Schema updated."); 303 log.info("Schema updated.");
304 } 304 }
305 break; 305 break;
  306 + case "3.1.1":
  307 + try (Connection conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword)) {
  308 + log.info("Updating schema ...");
  309 + schemaUpdateFile = Paths.get(installScripts.getDataDir(), "upgrade", "3.1.1", SCHEMA_UPDATE_SQL);
  310 + loadSql(schemaUpdateFile, conn);
  311 + log.info("Schema updated.");
  312 + }
  313 + break;
306 default: 314 default:
307 throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion); 315 throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
308 } 316 }
@@ -19,6 +19,8 @@ public interface SystemDataLoaderService { @@ -19,6 +19,8 @@ public interface SystemDataLoaderService {
19 19
20 void createSysAdmin() throws Exception; 20 void createSysAdmin() throws Exception;
21 21
  22 + void createDefaultTenantProfile() throws Exception;
  23 +
22 void createAdminSettings() throws Exception; 24 void createAdminSettings() throws Exception;
23 25
24 void loadSystemWidgets() throws Exception; 26 void loadSystemWidgets() throws Exception;
@@ -19,7 +19,9 @@ import lombok.extern.slf4j.Slf4j; @@ -19,7 +19,9 @@ import lombok.extern.slf4j.Slf4j;
19 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; 19 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
20 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
21 import org.thingsboard.server.common.data.Tenant; 21 import org.thingsboard.server.common.data.Tenant;
  22 +import org.thingsboard.server.common.data.TenantProfile;
22 import org.thingsboard.server.common.data.id.TenantId; 23 import org.thingsboard.server.common.data.id.TenantId;
  24 +import org.thingsboard.server.dao.tenant.TenantProfileService;
23 import org.thingsboard.server.dao.tenant.TenantService; 25 import org.thingsboard.server.dao.tenant.TenantService;
24 import org.thingsboard.server.queue.discovery.TenantRoutingInfo; 26 import org.thingsboard.server.queue.discovery.TenantRoutingInfo;
25 import org.thingsboard.server.queue.discovery.TenantRoutingInfoService; 27 import org.thingsboard.server.queue.discovery.TenantRoutingInfoService;
@@ -31,15 +33,20 @@ public class DefaultTenantRoutingInfoService implements TenantRoutingInfoService @@ -31,15 +33,20 @@ public class DefaultTenantRoutingInfoService implements TenantRoutingInfoService
31 33
32 private final TenantService tenantService; 34 private final TenantService tenantService;
33 35
34 - public DefaultTenantRoutingInfoService(TenantService tenantService) { 36 + private final TenantProfileService tenantProfileService;
  37 +
  38 + public DefaultTenantRoutingInfoService(TenantService tenantService, TenantProfileService tenantProfileService) {
35 this.tenantService = tenantService; 39 this.tenantService = tenantService;
  40 + this.tenantProfileService = tenantProfileService;
36 } 41 }
37 42
38 @Override 43 @Override
39 public TenantRoutingInfo getRoutingInfo(TenantId tenantId) { 44 public TenantRoutingInfo getRoutingInfo(TenantId tenantId) {
40 Tenant tenant = tenantService.findTenantById(tenantId); 45 Tenant tenant = tenantService.findTenantById(tenantId);
41 if (tenant != null) { 46 if (tenant != null) {
42 - return new TenantRoutingInfo(tenantId, tenant.isIsolatedTbCore(), tenant.isIsolatedTbRuleEngine()); 47 + // TODO: Tenant Profile from cache
  48 + TenantProfile tenantProfile = tenantProfileService.findTenantProfileById(tenantId, tenant.getTenantProfileId());
  49 + return new TenantRoutingInfo(tenantId, tenantProfile.isIsolatedTbCore(), tenantProfile.isIsolatedTbRuleEngine());
43 } else { 50 } else {
44 throw new RuntimeException("Tenant not found!"); 51 throw new RuntimeException("Tenant not found!");
45 } 52 }
@@ -28,6 +28,7 @@ import org.springframework.util.StringUtils; @@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
28 import org.thingsboard.server.common.data.DataConstants; 28 import org.thingsboard.server.common.data.DataConstants;
29 import org.thingsboard.server.common.data.Device; 29 import org.thingsboard.server.common.data.Device;
30 import org.thingsboard.server.common.data.Tenant; 30 import org.thingsboard.server.common.data.Tenant;
  31 +import org.thingsboard.server.common.data.TenantProfile;
31 import org.thingsboard.server.common.data.id.CustomerId; 32 import org.thingsboard.server.common.data.id.CustomerId;
32 import org.thingsboard.server.common.data.id.DeviceId; 33 import org.thingsboard.server.common.data.id.DeviceId;
33 import org.thingsboard.server.common.data.id.TenantId; 34 import org.thingsboard.server.common.data.id.TenantId;
@@ -40,6 +41,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData; @@ -40,6 +41,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
40 import org.thingsboard.server.dao.device.DeviceCredentialsService; 41 import org.thingsboard.server.dao.device.DeviceCredentialsService;
41 import org.thingsboard.server.dao.device.DeviceService; 42 import org.thingsboard.server.dao.device.DeviceService;
42 import org.thingsboard.server.dao.relation.RelationService; 43 import org.thingsboard.server.dao.relation.RelationService;
  44 +import org.thingsboard.server.dao.tenant.TenantProfileService;
43 import org.thingsboard.server.dao.tenant.TenantService; 45 import org.thingsboard.server.dao.tenant.TenantService;
44 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto; 46 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
45 import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg; 47 import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
@@ -78,6 +80,9 @@ public class DefaultTransportApiService implements TransportApiService { @@ -78,6 +80,9 @@ public class DefaultTransportApiService implements TransportApiService {
78 private TenantService tenantService; 80 private TenantService tenantService;
79 81
80 @Autowired 82 @Autowired
  83 + private TenantProfileService tenantProfileService;
  84 +
  85 + @Autowired
81 private DeviceService deviceService; 86 private DeviceService deviceService;
82 87
83 @Autowired 88 @Autowired
@@ -168,10 +173,13 @@ public class DefaultTransportApiService implements TransportApiService { @@ -168,10 +173,13 @@ public class DefaultTransportApiService implements TransportApiService {
168 173
169 private ListenableFuture<TransportApiResponseMsg> handle(GetTenantRoutingInfoRequestMsg requestMsg) { 174 private ListenableFuture<TransportApiResponseMsg> handle(GetTenantRoutingInfoRequestMsg requestMsg) {
170 TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB())); 175 TenantId tenantId = new TenantId(new UUID(requestMsg.getTenantIdMSB(), requestMsg.getTenantIdLSB()));
171 - ListenableFuture<Tenant> tenantFuture = tenantService.findTenantByIdAsync(TenantId.SYS_TENANT_ID, tenantId);  
172 - return Futures.transform(tenantFuture, tenant -> TransportApiResponseMsg.newBuilder()  
173 - .setGetTenantRoutingInfoResponseMsg(GetTenantRoutingInfoResponseMsg.newBuilder().setIsolatedTbCore(tenant.isIsolatedTbCore())  
174 - .setIsolatedTbRuleEngine(tenant.isIsolatedTbRuleEngine()).build()).build(), dbCallbackExecutorService); 176 + // TODO: Tenant Profile from cache
  177 + ListenableFuture<TenantProfile> tenantProfileFuture =
  178 + Futures.transform(tenantService.findTenantByIdAsync(TenantId.SYS_TENANT_ID, tenantId), tenant ->
  179 + tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, tenant.getTenantProfileId()), dbCallbackExecutorService);
  180 + return Futures.transform(tenantProfileFuture, tenantProfile -> TransportApiResponseMsg.newBuilder()
  181 + .setGetTenantRoutingInfoResponseMsg(GetTenantRoutingInfoResponseMsg.newBuilder().setIsolatedTbCore(tenantProfile.isIsolatedTbCore())
  182 + .setIsolatedTbRuleEngine(tenantProfile.isIsolatedTbRuleEngine()).build()).build(), dbCallbackExecutorService);
175 } 183 }
176 184
177 private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) { 185 private ListenableFuture<TransportApiResponseMsg> getDeviceInfo(DeviceId deviceId, DeviceCredentials credentials) {
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.device;
  17 +
  18 +import org.thingsboard.server.common.data.DeviceProfile;
  19 +import org.thingsboard.server.common.data.EntityInfo;
  20 +import org.thingsboard.server.common.data.id.DeviceProfileId;
  21 +import org.thingsboard.server.common.data.id.TenantId;
  22 +import org.thingsboard.server.common.data.page.PageData;
  23 +import org.thingsboard.server.common.data.page.PageLink;
  24 +
  25 +public interface DeviceProfileService {
  26 +
  27 + DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId);
  28 +
  29 + EntityInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId);
  30 +
  31 + DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile);
  32 +
  33 + void deleteDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId);
  34 +
  35 + PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink);
  36 +
  37 + PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink);
  38 +
  39 + DeviceProfile createDefaultDeviceProfile(TenantId tenantId);
  40 +
  41 + DeviceProfile findDefaultDeviceProfile(TenantId tenantId);
  42 +
  43 + EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId);
  44 +
  45 + boolean setDefaultDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId);
  46 +
  47 + void deleteDeviceProfilesByTenantId(TenantId tenantId);
  48 +
  49 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.tenant;
  17 +
  18 +import org.thingsboard.server.common.data.EntityInfo;
  19 +import org.thingsboard.server.common.data.TenantProfile;
  20 +import org.thingsboard.server.common.data.id.TenantId;
  21 +import org.thingsboard.server.common.data.id.TenantProfileId;
  22 +import org.thingsboard.server.common.data.page.PageData;
  23 +import org.thingsboard.server.common.data.page.PageLink;
  24 +
  25 +public interface TenantProfileService {
  26 +
  27 + TenantProfile findTenantProfileById(TenantId tenantId, TenantProfileId tenantProfileId);
  28 +
  29 + EntityInfo findTenantProfileInfoById(TenantId tenantId, TenantProfileId tenantProfileId);
  30 +
  31 + TenantProfile saveTenantProfile(TenantId tenantId, TenantProfile tenantProfile);
  32 +
  33 + void deleteTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId);
  34 +
  35 + PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink);
  36 +
  37 + PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink);
  38 +
  39 + TenantProfile findOrCreateDefaultTenantProfile(TenantId tenantId);
  40 +
  41 + TenantProfile findDefaultTenantProfile(TenantId tenantId);
  42 +
  43 + EntityInfo findDefaultTenantProfileInfo(TenantId tenantId);
  44 +
  45 + boolean setDefaultTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId);
  46 +
  47 + void deleteTenantProfiles(TenantId tenantId);
  48 +
  49 +}
@@ -18,6 +18,7 @@ package org.thingsboard.server.common.data; @@ -18,6 +18,7 @@ package org.thingsboard.server.common.data;
18 import lombok.EqualsAndHashCode; 18 import lombok.EqualsAndHashCode;
19 import org.thingsboard.server.common.data.id.CustomerId; 19 import org.thingsboard.server.common.data.id.CustomerId;
20 import org.thingsboard.server.common.data.id.DeviceId; 20 import org.thingsboard.server.common.data.id.DeviceId;
  21 +import org.thingsboard.server.common.data.id.DeviceProfileId;
21 import org.thingsboard.server.common.data.id.TenantId; 22 import org.thingsboard.server.common.data.id.TenantId;
22 23
23 @EqualsAndHashCode(callSuper = true) 24 @EqualsAndHashCode(callSuper = true)
@@ -30,6 +31,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen @@ -30,6 +31,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
30 private String name; 31 private String name;
31 private String type; 32 private String type;
32 private String label; 33 private String label;
  34 + private DeviceProfileId deviceProfileId;
33 35
34 public Device() { 36 public Device() {
35 super(); 37 super();
@@ -46,6 +48,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen @@ -46,6 +48,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
46 this.name = device.getName(); 48 this.name = device.getName();
47 this.type = device.getType(); 49 this.type = device.getType();
48 this.label = device.getLabel(); 50 this.label = device.getLabel();
  51 + this.deviceProfileId = device.getDeviceProfileId();
49 } 52 }
50 53
51 public TenantId getTenantId() { 54 public TenantId getTenantId() {
@@ -89,6 +92,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen @@ -89,6 +92,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
89 this.label = label; 92 this.label = label;
90 } 93 }
91 94
  95 + public DeviceProfileId getDeviceProfileId() {
  96 + return deviceProfileId;
  97 + }
  98 +
  99 + public void setDeviceProfileId(DeviceProfileId deviceProfileId) {
  100 + this.deviceProfileId = deviceProfileId;
  101 + }
  102 +
92 @Override 103 @Override
93 public String getSearchText() { 104 public String getSearchText() {
94 return getName(); 105 return getName();
@@ -107,6 +118,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen @@ -107,6 +118,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
107 builder.append(type); 118 builder.append(type);
108 builder.append(", label="); 119 builder.append(", label=");
109 builder.append(label); 120 builder.append(label);
  121 + builder.append(", deviceProfileId=");
  122 + builder.append(deviceProfileId);
110 builder.append(", additionalInfo="); 123 builder.append(", additionalInfo=");
111 builder.append(getAdditionalInfo()); 124 builder.append(getAdditionalInfo());
112 builder.append(", createdTime="); 125 builder.append(", createdTime=");
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.databind.JsonNode;
  20 +import lombok.Data;
  21 +import lombok.EqualsAndHashCode;
  22 +import org.thingsboard.server.common.data.id.DeviceProfileId;
  23 +import org.thingsboard.server.common.data.id.RuleChainId;
  24 +import org.thingsboard.server.common.data.id.TenantId;
  25 +
  26 +import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.getJson;
  27 +import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.setJson;
  28 +
  29 +@Data
  30 +@EqualsAndHashCode(callSuper = true)
  31 +public class DeviceProfile extends SearchTextBased<DeviceProfileId> implements HasName {
  32 +
  33 + private TenantId tenantId;
  34 + private String name;
  35 + private String description;
  36 + private boolean isDefault;
  37 + private RuleChainId defaultRuleChainId;
  38 + private transient JsonNode profileData;
  39 + @JsonIgnore
  40 + private byte[] profileDataBytes;
  41 +
  42 + public DeviceProfile() {
  43 + super();
  44 + }
  45 +
  46 + public DeviceProfile(DeviceProfileId deviceProfileId) {
  47 + super(deviceProfileId);
  48 + }
  49 +
  50 + public DeviceProfile(DeviceProfile deviceProfile) {
  51 + super(deviceProfile);
  52 + this.tenantId = deviceProfile.getTenantId();
  53 + this.name = deviceProfile.getName();
  54 + this.description = deviceProfile.getDescription();
  55 + this.isDefault = deviceProfile.isDefault();
  56 + this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId();
  57 + this.setProfileData(deviceProfile.getProfileData());
  58 + }
  59 +
  60 + @Override
  61 + public String getSearchText() {
  62 + return getName();
  63 + }
  64 +
  65 + @Override
  66 + public String getName() {
  67 + return name;
  68 + }
  69 +
  70 + public JsonNode getProfileData() {
  71 + return getJson(() -> profileData, () -> profileDataBytes);
  72 + }
  73 +
  74 + public void setProfileData(JsonNode data) {
  75 + setJson(data, json -> this.profileData = json, bytes -> this.profileDataBytes = bytes);
  76 + }
  77 +
  78 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data;
  17 +
  18 +import lombok.Data;
  19 +import org.thingsboard.server.common.data.id.EntityId;
  20 +import org.thingsboard.server.common.data.id.EntityIdFactory;
  21 +import org.thingsboard.server.common.data.id.HasId;
  22 +
  23 +import java.util.UUID;
  24 +
  25 +@Data
  26 +public class EntityInfo implements HasId<EntityId>, HasName {
  27 +
  28 + private final EntityId id;
  29 + private final String name;
  30 +
  31 + public EntityInfo(EntityId id, String name) {
  32 + this.id = id;
  33 + this.name = name;
  34 + }
  35 +
  36 + public EntityInfo(UUID uuid, String type, String name) {
  37 + this.id = EntityIdFactory.getByTypeAndUuid(type, uuid);
  38 + this.name = name;
  39 + }
  40 +
  41 +}
@@ -19,5 +19,5 @@ package org.thingsboard.server.common.data; @@ -19,5 +19,5 @@ package org.thingsboard.server.common.data;
19 * @author Andrew Shvayka 19 * @author Andrew Shvayka
20 */ 20 */
21 public enum EntityType { 21 public enum EntityType {
22 - TENANT, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE 22 + TENANT, TENANT_PROFILE, CUSTOMER, USER, DASHBOARD, ASSET, DEVICE, DEVICE_PROFILE, ALARM, RULE_CHAIN, RULE_NODE, ENTITY_VIEW, WIDGETS_BUNDLE, WIDGET_TYPE
23 } 23 }
@@ -19,8 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; @@ -19,8 +19,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
19 import com.fasterxml.jackson.annotation.JsonProperty; 19 import com.fasterxml.jackson.annotation.JsonProperty;
20 import lombok.EqualsAndHashCode; 20 import lombok.EqualsAndHashCode;
21 import org.thingsboard.server.common.data.id.TenantId; 21 import org.thingsboard.server.common.data.id.TenantId;
22 -  
23 -import com.fasterxml.jackson.databind.JsonNode; 22 +import org.thingsboard.server.common.data.id.TenantProfileId;
24 23
25 @EqualsAndHashCode(callSuper = true) 24 @EqualsAndHashCode(callSuper = true)
26 public class Tenant extends ContactBased<TenantId> implements HasTenantId { 25 public class Tenant extends ContactBased<TenantId> implements HasTenantId {
@@ -29,8 +28,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { @@ -29,8 +28,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
29 28
30 private String title; 29 private String title;
31 private String region; 30 private String region;
32 - private boolean isolatedTbCore;  
33 - private boolean isolatedTbRuleEngine; 31 + private TenantProfileId tenantProfileId;
34 32
35 public Tenant() { 33 public Tenant() {
36 super(); 34 super();
@@ -44,6 +42,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { @@ -44,6 +42,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
44 super(tenant); 42 super(tenant);
45 this.title = tenant.getTitle(); 43 this.title = tenant.getTitle();
46 this.region = tenant.getRegion(); 44 this.region = tenant.getRegion();
  45 + this.tenantProfileId = tenant.getTenantProfileId();
47 } 46 }
48 47
49 public String getTitle() { 48 public String getTitle() {
@@ -74,20 +73,12 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { @@ -74,20 +73,12 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
74 this.region = region; 73 this.region = region;
75 } 74 }
76 75
77 - public boolean isIsolatedTbCore() {  
78 - return isolatedTbCore;  
79 - }  
80 -  
81 - public void setIsolatedTbCore(boolean isolatedTbCore) {  
82 - this.isolatedTbCore = isolatedTbCore;  
83 - }  
84 -  
85 - public boolean isIsolatedTbRuleEngine() {  
86 - return isolatedTbRuleEngine; 76 + public TenantProfileId getTenantProfileId() {
  77 + return tenantProfileId;
87 } 78 }
88 79
89 - public void setIsolatedTbRuleEngine(boolean isolatedTbRuleEngine) {  
90 - this.isolatedTbRuleEngine = isolatedTbRuleEngine; 80 + public void setTenantProfileId(TenantProfileId tenantProfileId) {
  81 + this.tenantProfileId = tenantProfileId;
91 } 82 }
92 83
93 @Override 84 @Override
@@ -102,10 +93,8 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId { @@ -102,10 +93,8 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
102 builder.append(title); 93 builder.append(title);
103 builder.append(", region="); 94 builder.append(", region=");
104 builder.append(region); 95 builder.append(region);
105 - builder.append(", isolatedTbCore=");  
106 - builder.append(isolatedTbCore);  
107 - builder.append(", isolatedTbRuleEngine=");  
108 - builder.append(isolatedTbRuleEngine); 96 + builder.append(", tenantProfileId=");
  97 + builder.append(tenantProfileId);
109 builder.append(", additionalInfo="); 98 builder.append(", additionalInfo=");
110 builder.append(getAdditionalInfo()); 99 builder.append(getAdditionalInfo());
111 builder.append(", country="); 100 builder.append(", country=");
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.databind.JsonNode;
  20 +import lombok.Data;
  21 +import lombok.EqualsAndHashCode;
  22 +import org.thingsboard.server.common.data.id.TenantProfileId;
  23 +
  24 +import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.getJson;
  25 +import static org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo.setJson;
  26 +
  27 +@Data
  28 +@EqualsAndHashCode(callSuper = true)
  29 +public class TenantProfile extends SearchTextBased<TenantProfileId> implements HasName {
  30 +
  31 + private String name;
  32 + private String description;
  33 + private boolean isDefault;
  34 + private boolean isolatedTbCore;
  35 + private boolean isolatedTbRuleEngine;
  36 + private transient JsonNode profileData;
  37 + @JsonIgnore
  38 + private byte[] profileDataBytes;
  39 +
  40 + public TenantProfile() {
  41 + super();
  42 + }
  43 +
  44 + public TenantProfile(TenantProfileId tenantProfileId) {
  45 + super(tenantProfileId);
  46 + }
  47 +
  48 + public TenantProfile(TenantProfile tenantProfile) {
  49 + super(tenantProfile);
  50 + this.name = tenantProfile.getName();
  51 + this.description = tenantProfile.getDescription();
  52 + this.isDefault = tenantProfile.isDefault();
  53 + this.isolatedTbCore = tenantProfile.isIsolatedTbCore();
  54 + this.isolatedTbRuleEngine = tenantProfile.isIsolatedTbRuleEngine();
  55 + this.setProfileData(tenantProfile.getProfileData());
  56 + }
  57 +
  58 + @Override
  59 + public String getSearchText() {
  60 + return getName();
  61 + }
  62 +
  63 + @Override
  64 + public String getName() {
  65 + return name;
  66 + }
  67 +
  68 + public JsonNode getProfileData() {
  69 + return getJson(() -> profileData, () -> profileDataBytes);
  70 + }
  71 +
  72 + public void setProfileData(JsonNode data) {
  73 + setJson(data, json -> this.profileData = json, bytes -> this.profileDataBytes = bytes);
  74 + }
  75 +
  76 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import java.util.UUID;
  19 +
  20 +import com.fasterxml.jackson.annotation.JsonCreator;
  21 +import com.fasterxml.jackson.annotation.JsonIgnore;
  22 +import com.fasterxml.jackson.annotation.JsonProperty;
  23 +import org.thingsboard.server.common.data.EntityType;
  24 +
  25 +public class DeviceProfileId extends UUIDBased implements EntityId {
  26 +
  27 + private static final long serialVersionUID = 1L;
  28 +
  29 + @JsonCreator
  30 + public DeviceProfileId(@JsonProperty("id") UUID id) {
  31 + super(id);
  32 + }
  33 +
  34 + public static DeviceProfileId fromString(String deviceProfileId) {
  35 + return new DeviceProfileId(UUID.fromString(deviceProfileId));
  36 + }
  37 +
  38 + @JsonIgnore
  39 + @Override
  40 + public EntityType getEntityType() {
  41 + return EntityType.DEVICE_PROFILE;
  42 + }
  43 +}
@@ -29,7 +29,7 @@ import java.util.UUID; @@ -29,7 +29,7 @@ import java.util.UUID;
29 29
30 @JsonDeserialize(using = EntityIdDeserializer.class) 30 @JsonDeserialize(using = EntityIdDeserializer.class)
31 @JsonSerialize(using = EntityIdSerializer.class) 31 @JsonSerialize(using = EntityIdSerializer.class)
32 -public interface EntityId extends Serializable { //NOSONAR, the constant is closely related to EntityId 32 +public interface EntityId extends HasUUID, Serializable { //NOSONAR, the constant is closely related to EntityId
33 33
34 UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080"); 34 UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080");
35 35
@@ -62,6 +62,10 @@ public class EntityIdFactory { @@ -62,6 +62,10 @@ public class EntityIdFactory {
62 return new WidgetsBundleId(uuid); 62 return new WidgetsBundleId(uuid);
63 case WIDGET_TYPE: 63 case WIDGET_TYPE:
64 return new WidgetTypeId(uuid); 64 return new WidgetTypeId(uuid);
  65 + case DEVICE_PROFILE:
  66 + return new DeviceProfileId(uuid);
  67 + case TENANT_PROFILE:
  68 + return new TenantProfileId(uuid);
65 } 69 }
66 throw new IllegalArgumentException("EntityType " + type + " is not supported!"); 70 throw new IllegalArgumentException("EntityType " + type + " is not supported!");
67 } 71 }
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import java.io.Serializable;
  19 +
  20 +public interface HasId<I extends HasUUID> extends Serializable {
  21 +
  22 + I getId();
  23 +
  24 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +
  17 +package org.thingsboard.server.common.data.id;
  18 +
  19 +import java.util.UUID;
  20 +
  21 +public interface HasUUID {
  22 +
  23 + UUID getId();
  24 +
  25 +}
@@ -20,7 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; @@ -20,7 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
20 import java.io.Serializable; 20 import java.io.Serializable;
21 import java.util.UUID; 21 import java.util.UUID;
22 22
23 -public abstract class IdBased<I extends UUIDBased> implements Serializable { 23 +public abstract class IdBased<I extends UUIDBased> implements HasId<I> {
24 24
25 protected I id; 25 protected I id;
26 26
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data.id;
  17 +
  18 +import java.util.UUID;
  19 +
  20 +import com.fasterxml.jackson.annotation.JsonCreator;
  21 +import com.fasterxml.jackson.annotation.JsonIgnore;
  22 +import com.fasterxml.jackson.annotation.JsonProperty;
  23 +import org.thingsboard.server.common.data.EntityType;
  24 +
  25 +public class TenantProfileId extends UUIDBased implements EntityId {
  26 +
  27 + private static final long serialVersionUID = 1L;
  28 +
  29 + @JsonCreator
  30 + public TenantProfileId(@JsonProperty("id") UUID id) {
  31 + super(id);
  32 + }
  33 +
  34 + public static TenantProfileId fromString(String tenantProfileId) {
  35 + return new TenantProfileId(UUID.fromString(tenantProfileId));
  36 + }
  37 +
  38 + @JsonIgnore
  39 + @Override
  40 + public EntityType getEntityType() {
  41 + return EntityType.TENANT_PROFILE;
  42 + }
  43 +}
@@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.id; @@ -18,7 +18,7 @@ package org.thingsboard.server.common.data.id;
18 import java.io.Serializable; 18 import java.io.Serializable;
19 import java.util.UUID; 19 import java.util.UUID;
20 20
21 -public abstract class UUIDBased implements Serializable { 21 +public abstract class UUIDBased implements HasUUID, Serializable {
22 22
23 private static final long serialVersionUID = 1L; 23 private static final long serialVersionUID = 1L;
24 24
@@ -43,6 +43,10 @@ public abstract class DaoUtil { @@ -43,6 +43,10 @@ public abstract class DaoUtil {
43 return new PageData(data, page.getTotalPages(), page.getTotalElements(), page.hasNext()); 43 return new PageData(data, page.getTotalPages(), page.getTotalElements(), page.hasNext());
44 } 44 }
45 45
  46 + public static <T> PageData<T> pageToPageData(Page<T> page) {
  47 + return new PageData(page.getContent(), page.getTotalPages(), page.getTotalElements(), page.hasNext());
  48 + }
  49 +
46 public static Pageable toPageable(PageLink pageLink) { 50 public static Pageable toPageable(PageLink pageLink) {
47 return toPageable(pageLink, Collections.emptyMap()); 51 return toPageable(pageLink, Collections.emptyMap());
48 } 52 }
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.device;
  17 +
  18 +import org.thingsboard.server.common.data.DeviceProfile;
  19 +import org.thingsboard.server.common.data.EntityInfo;
  20 +import org.thingsboard.server.common.data.id.TenantId;
  21 +import org.thingsboard.server.common.data.page.PageData;
  22 +import org.thingsboard.server.common.data.page.PageLink;
  23 +import org.thingsboard.server.dao.Dao;
  24 +
  25 +import java.util.UUID;
  26 +
  27 +public interface DeviceProfileDao extends Dao<DeviceProfile> {
  28 +
  29 + EntityInfo findDeviceProfileInfoById(TenantId tenantId, UUID deviceProfileId);
  30 +
  31 + DeviceProfile save(TenantId tenantId, DeviceProfile deviceProfile);
  32 +
  33 + PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink);
  34 +
  35 + PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink);
  36 +
  37 + DeviceProfile findDefaultDeviceProfile(TenantId tenantId);
  38 +
  39 + EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId);
  40 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.device;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.apache.commons.lang3.StringUtils;
  20 +import org.hibernate.exception.ConstraintViolationException;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.stereotype.Service;
  23 +import org.thingsboard.server.common.data.DeviceProfile;
  24 +import org.thingsboard.server.common.data.EntityInfo;
  25 +import org.thingsboard.server.common.data.Tenant;
  26 +import org.thingsboard.server.common.data.id.DeviceProfileId;
  27 +import org.thingsboard.server.common.data.id.TenantId;
  28 +import org.thingsboard.server.common.data.page.PageData;
  29 +import org.thingsboard.server.common.data.page.PageLink;
  30 +import org.thingsboard.server.dao.entity.AbstractEntityService;
  31 +import org.thingsboard.server.dao.exception.DataValidationException;
  32 +import org.thingsboard.server.dao.service.DataValidator;
  33 +import org.thingsboard.server.dao.service.PaginatedRemover;
  34 +import org.thingsboard.server.dao.service.Validator;
  35 +import org.thingsboard.server.dao.tenant.TenantDao;
  36 +import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  37 +
  38 +import static org.thingsboard.server.dao.service.Validator.validateId;
  39 +
  40 +@Service
  41 +@Slf4j
  42 +public class DeviceProfileServiceImpl extends AbstractEntityService implements DeviceProfileService {
  43 +
  44 + private static final String INCORRECT_TENANT_ID = "Incorrect tenantId ";
  45 + private static final String INCORRECT_DEVICE_PROFILE_ID = "Incorrect deviceProfileId ";
  46 +
  47 + @Autowired
  48 + private DeviceProfileDao deviceProfileDao;
  49 +
  50 + @Autowired
  51 + private TenantDao tenantDao;
  52 +
  53 + @Override
  54 + public DeviceProfile findDeviceProfileById(TenantId tenantId, DeviceProfileId deviceProfileId) {
  55 + log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
  56 + Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
  57 + return deviceProfileDao.findById(tenantId, deviceProfileId.getId());
  58 + }
  59 +
  60 + @Override
  61 + public EntityInfo findDeviceProfileInfoById(TenantId tenantId, DeviceProfileId deviceProfileId) {
  62 + log.trace("Executing findDeviceProfileById [{}]", deviceProfileId);
  63 + Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
  64 + return deviceProfileDao.findDeviceProfileInfoById(tenantId, deviceProfileId.getId());
  65 + }
  66 +
  67 + @Override
  68 + public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) {
  69 + log.trace("Executing saveDeviceProfile [{}]", deviceProfile);
  70 + deviceProfileValidator.validate(deviceProfile, DeviceProfile::getTenantId);
  71 + DeviceProfile savedDeviceProfile;
  72 + try {
  73 + savedDeviceProfile = deviceProfileDao.save(deviceProfile.getTenantId(), deviceProfile);
  74 + } catch (Exception t) {
  75 + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
  76 + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("device_profile_name_unq_key")) {
  77 + throw new DataValidationException("Device profile with such name already exists!");
  78 + } else {
  79 + throw t;
  80 + }
  81 + }
  82 + return savedDeviceProfile;
  83 + }
  84 +
  85 + @Override
  86 + public void deleteDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
  87 + log.trace("Executing deleteDeviceProfile [{}]", deviceProfileId);
  88 + Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
  89 + deleteEntityRelations(tenantId, deviceProfileId);
  90 + deviceProfileDao.removeById(tenantId, deviceProfileId.getId());
  91 + }
  92 +
  93 + @Override
  94 + public PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink) {
  95 + log.trace("Executing findDeviceProfiles tenantId [{}], pageLink [{}]", tenantId, pageLink);
  96 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  97 + Validator.validatePageLink(pageLink);
  98 + return deviceProfileDao.findDeviceProfiles(tenantId, pageLink);
  99 + }
  100 +
  101 + @Override
  102 + public PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink) {
  103 + log.trace("Executing findDeviceProfileInfos tenantId [{}], pageLink [{}]", tenantId, pageLink);
  104 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  105 + Validator.validatePageLink(pageLink);
  106 + return deviceProfileDao.findDeviceProfileInfos(tenantId, pageLink);
  107 + }
  108 +
  109 + @Override
  110 + public DeviceProfile createDefaultDeviceProfile(TenantId tenantId) {
  111 + log.trace("Executing createDefaultDeviceProfile tenantId [{}]", tenantId);
  112 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  113 + DeviceProfile deviceProfile = new DeviceProfile();
  114 + deviceProfile.setTenantId(tenantId);
  115 + deviceProfile.setDefault(true);
  116 + deviceProfile.setName("Default");
  117 + deviceProfile.setDescription("Default device profile");
  118 + deviceProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
  119 + return deviceProfileDao.save(tenantId, deviceProfile);
  120 + }
  121 +
  122 + @Override
  123 + public DeviceProfile findDefaultDeviceProfile(TenantId tenantId) {
  124 + log.trace("Executing findDefaultDeviceProfile tenantId [{}]", tenantId);
  125 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  126 + return deviceProfileDao.findDefaultDeviceProfile(tenantId);
  127 + }
  128 +
  129 + @Override
  130 + public EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId) {
  131 + log.trace("Executing findDefaultDeviceProfileInfo tenantId [{}]", tenantId);
  132 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  133 + return deviceProfileDao.findDefaultDeviceProfileInfo(tenantId);
  134 + }
  135 +
  136 + @Override
  137 + public boolean setDefaultDeviceProfile(TenantId tenantId, DeviceProfileId deviceProfileId) {
  138 + log.trace("Executing setDefaultDeviceProfile [{}]", deviceProfileId);
  139 + Validator.validateId(deviceProfileId, INCORRECT_DEVICE_PROFILE_ID + deviceProfileId);
  140 + DeviceProfile deviceProfile = deviceProfileDao.findById(tenantId, deviceProfileId.getId());
  141 + if (!deviceProfile.isDefault()) {
  142 + deviceProfile.setDefault(true);
  143 + DeviceProfile previousDefaultDeviceProfile = findDefaultDeviceProfile(tenantId);
  144 + if (previousDefaultDeviceProfile == null) {
  145 + deviceProfileDao.save(tenantId, deviceProfile);
  146 + return true;
  147 + } else if (!previousDefaultDeviceProfile.getId().equals(deviceProfile.getId())) {
  148 + previousDefaultDeviceProfile.setDefault(false);
  149 + deviceProfileDao.save(tenantId, previousDefaultDeviceProfile);
  150 + deviceProfileDao.save(tenantId, deviceProfile);
  151 + return true;
  152 + }
  153 + }
  154 + return false;
  155 + }
  156 +
  157 + @Override
  158 + public void deleteDeviceProfilesByTenantId(TenantId tenantId) {
  159 + log.trace("Executing deleteDeviceProfilesByTenantId, tenantId [{}]", tenantId);
  160 + validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
  161 + tenantDeviceProfilesRemover.removeEntities(tenantId, tenantId);
  162 + }
  163 +
  164 + private DataValidator<DeviceProfile> deviceProfileValidator =
  165 + new DataValidator<DeviceProfile>() {
  166 + @Override
  167 + protected void validateDataImpl(TenantId tenantId, DeviceProfile deviceProfile) {
  168 + if (StringUtils.isEmpty(deviceProfile.getName())) {
  169 + throw new DataValidationException("Device profile name should be specified!");
  170 + }
  171 + if (deviceProfile.getTenantId() == null) {
  172 + throw new DataValidationException("Device profile should be assigned to tenant!");
  173 + } else {
  174 + Tenant tenant = tenantDao.findById(deviceProfile.getTenantId(), deviceProfile.getTenantId().getId());
  175 + if (tenant == null) {
  176 + throw new DataValidationException("Device profile is referencing to non-existent tenant!");
  177 + }
  178 + }
  179 + if (deviceProfile.isDefault()) {
  180 + DeviceProfile defaultDeviceProfile = findDefaultDeviceProfile(tenantId);
  181 + if (defaultDeviceProfile != null && !defaultDeviceProfile.getId().equals(deviceProfile.getId())) {
  182 + throw new DataValidationException("Another default device profile is present in scope of current tenant!");
  183 + }
  184 + }
  185 + }
  186 + };
  187 +
  188 + private PaginatedRemover<TenantId, DeviceProfile> tenantDeviceProfilesRemover =
  189 + new PaginatedRemover<TenantId, DeviceProfile>() {
  190 +
  191 + @Override
  192 + protected PageData<DeviceProfile> findEntities(TenantId tenantId, TenantId id, PageLink pageLink) {
  193 + return deviceProfileDao.findDeviceProfiles(id, pageLink);
  194 + }
  195 +
  196 + @Override
  197 + protected void removeEntity(TenantId tenantId, DeviceProfile entity) {
  198 + deleteDeviceProfile(tenantId, new DeviceProfileId(entity.getUuidId()));
  199 + }
  200 + };
  201 +
  202 +}
@@ -34,6 +34,8 @@ import org.springframework.util.StringUtils; @@ -34,6 +34,8 @@ import org.springframework.util.StringUtils;
34 import org.thingsboard.server.common.data.Customer; 34 import org.thingsboard.server.common.data.Customer;
35 import org.thingsboard.server.common.data.Device; 35 import org.thingsboard.server.common.data.Device;
36 import org.thingsboard.server.common.data.DeviceInfo; 36 import org.thingsboard.server.common.data.DeviceInfo;
  37 +import org.thingsboard.server.common.data.DeviceProfile;
  38 +import org.thingsboard.server.common.data.EntityInfo;
37 import org.thingsboard.server.common.data.EntitySubtype; 39 import org.thingsboard.server.common.data.EntitySubtype;
38 import org.thingsboard.server.common.data.EntityType; 40 import org.thingsboard.server.common.data.EntityType;
39 import org.thingsboard.server.common.data.EntityView; 41 import org.thingsboard.server.common.data.EntityView;
@@ -41,6 +43,7 @@ import org.thingsboard.server.common.data.Tenant; @@ -41,6 +43,7 @@ import org.thingsboard.server.common.data.Tenant;
41 import org.thingsboard.server.common.data.device.DeviceSearchQuery; 43 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
42 import org.thingsboard.server.common.data.id.CustomerId; 44 import org.thingsboard.server.common.data.id.CustomerId;
43 import org.thingsboard.server.common.data.id.DeviceId; 45 import org.thingsboard.server.common.data.id.DeviceId;
  46 +import org.thingsboard.server.common.data.id.DeviceProfileId;
44 import org.thingsboard.server.common.data.id.EntityId; 47 import org.thingsboard.server.common.data.id.EntityId;
45 import org.thingsboard.server.common.data.id.TenantId; 48 import org.thingsboard.server.common.data.id.TenantId;
46 import org.thingsboard.server.common.data.page.PageData; 49 import org.thingsboard.server.common.data.page.PageData;
@@ -96,6 +99,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe @@ -96,6 +99,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
96 private DeviceCredentialsService deviceCredentialsService; 99 private DeviceCredentialsService deviceCredentialsService;
97 100
98 @Autowired 101 @Autowired
  102 + private DeviceProfileService deviceProfileService;
  103 +
  104 + @Autowired
99 private EntityViewService entityViewService; 105 private EntityViewService entityViewService;
100 106
101 @Autowired 107 @Autowired
@@ -159,6 +165,10 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe @@ -159,6 +165,10 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
159 deviceValidator.validate(device, Device::getTenantId); 165 deviceValidator.validate(device, Device::getTenantId);
160 Device savedDevice; 166 Device savedDevice;
161 try { 167 try {
  168 + if (device.getDeviceProfileId() == null) {
  169 + EntityInfo deviceProfile = this.deviceProfileService.findDefaultDeviceProfileInfo(device.getTenantId());
  170 + device.setDeviceProfileId(new DeviceProfileId(deviceProfile.getId().getId()));
  171 + }
162 savedDevice = deviceDao.save(device.getTenantId(), device); 172 savedDevice = deviceDao.save(device.getTenantId(), device);
163 } catch (Exception t) { 173 } catch (Exception t) {
164 ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); 174 ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
@@ -114,12 +114,22 @@ public class ModelConstants { @@ -114,12 +114,22 @@ public class ModelConstants {
114 public static final String TENANT_TITLE_PROPERTY = TITLE_PROPERTY; 114 public static final String TENANT_TITLE_PROPERTY = TITLE_PROPERTY;
115 public static final String TENANT_REGION_PROPERTY = "region"; 115 public static final String TENANT_REGION_PROPERTY = "region";
116 public static final String TENANT_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; 116 public static final String TENANT_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
117 - public static final String TENANT_ISOLATED_TB_CORE = "isolated_tb_core";  
118 - public static final String TENANT_ISOLATED_TB_RULE_ENGINE = "isolated_tb_rule_engine"; 117 + public static final String TENANT_TENANT_PROFILE_ID_PROPERTY = "tenant_profile_id";
119 118
120 public static final String TENANT_BY_REGION_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "tenant_by_region_and_search_text"; 119 public static final String TENANT_BY_REGION_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "tenant_by_region_and_search_text";
121 120
122 /** 121 /**
  122 + * Tenant profile constants.
  123 + */
  124 + public static final String TENANT_PROFILE_COLUMN_FAMILY_NAME = "tenant_profile";
  125 + public static final String TENANT_PROFILE_NAME_PROPERTY = "name";
  126 + public static final String TENANT_PROFILE_PROFILE_DATA_PROPERTY = "profile_data";
  127 + public static final String TENANT_PROFILE_DESCRIPTION_PROPERTY = "description";
  128 + public static final String TENANT_PROFILE_IS_DEFAULT_PROPERTY = "is_default";
  129 + public static final String TENANT_PROFILE_ISOLATED_TB_CORE = "isolated_tb_core";
  130 + public static final String TENANT_PROFILE_ISOLATED_TB_RULE_ENGINE = "isolated_tb_rule_engine";
  131 +
  132 + /**
123 * Cassandra customer constants. 133 * Cassandra customer constants.
124 */ 134 */
125 public static final String CUSTOMER_COLUMN_FAMILY_NAME = "customer"; 135 public static final String CUSTOMER_COLUMN_FAMILY_NAME = "customer";
@@ -141,6 +151,7 @@ public class ModelConstants { @@ -141,6 +151,7 @@ public class ModelConstants {
141 public static final String DEVICE_TYPE_PROPERTY = "type"; 151 public static final String DEVICE_TYPE_PROPERTY = "type";
142 public static final String DEVICE_LABEL_PROPERTY = "label"; 152 public static final String DEVICE_LABEL_PROPERTY = "label";
143 public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY; 153 public static final String DEVICE_ADDITIONAL_INFO_PROPERTY = ADDITIONAL_INFO_PROPERTY;
  154 + public static final String DEVICE_DEVICE_PROFILE_ID_PROPERTY = "device_profile_id";
144 public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text"; 155 public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text";
145 public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text"; 156 public static final String DEVICE_BY_TENANT_BY_TYPE_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_by_type_and_search_text";
146 public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text"; 157 public static final String DEVICE_BY_CUSTOMER_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_customer_and_search_text";
@@ -149,6 +160,17 @@ public class ModelConstants { @@ -149,6 +160,17 @@ public class ModelConstants {
149 public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant"; 160 public static final String DEVICE_TYPES_BY_TENANT_VIEW_NAME = "device_types_by_tenant";
150 161
151 /** 162 /**
  163 + * Device profile constants.
  164 + */
  165 + public static final String DEVICE_PROFILE_COLUMN_FAMILY_NAME = "device_profile";
  166 + public static final String DEVICE_PROFILE_TENANT_ID_PROPERTY = TENANT_ID_PROPERTY;
  167 + public static final String DEVICE_PROFILE_NAME_PROPERTY = "name";
  168 + public static final String DEVICE_PROFILE_PROFILE_DATA_PROPERTY = "profile_data";
  169 + public static final String DEVICE_PROFILE_DESCRIPTION_PROPERTY = "description";
  170 + public static final String DEVICE_PROFILE_IS_DEFAULT_PROPERTY = "is_default";
  171 + public static final String DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY = "default_rule_chain_id";
  172 +
  173 + /**
152 * Cassandra entityView constants. 174 * Cassandra entityView constants.
153 */ 175 */
154 public static final String ENTITY_VIEW_TABLE_FAMILY_NAME = "entity_view"; 176 public static final String ENTITY_VIEW_TABLE_FAMILY_NAME = "entity_view";
@@ -23,6 +23,7 @@ import org.hibernate.annotations.TypeDef; @@ -23,6 +23,7 @@ import org.hibernate.annotations.TypeDef;
23 import org.thingsboard.server.common.data.Device; 23 import org.thingsboard.server.common.data.Device;
24 import org.thingsboard.server.common.data.id.CustomerId; 24 import org.thingsboard.server.common.data.id.CustomerId;
25 import org.thingsboard.server.common.data.id.DeviceId; 25 import org.thingsboard.server.common.data.id.DeviceId;
  26 +import org.thingsboard.server.common.data.id.DeviceProfileId;
26 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
27 import org.thingsboard.server.dao.model.BaseSqlEntity; 28 import org.thingsboard.server.dao.model.BaseSqlEntity;
28 import org.thingsboard.server.dao.model.ModelConstants; 29 import org.thingsboard.server.dao.model.ModelConstants;
@@ -61,6 +62,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti @@ -61,6 +62,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
61 @Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY) 62 @Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY)
62 private JsonNode additionalInfo; 63 private JsonNode additionalInfo;
63 64
  65 + @Column(name = ModelConstants.DEVICE_DEVICE_PROFILE_ID_PROPERTY, columnDefinition = "uuid")
  66 + private UUID deviceProfileId;
  67 +
64 public AbstractDeviceEntity() { 68 public AbstractDeviceEntity() {
65 super(); 69 super();
66 } 70 }
@@ -76,6 +80,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti @@ -76,6 +80,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
76 if (device.getCustomerId() != null) { 80 if (device.getCustomerId() != null) {
77 this.customerId = device.getCustomerId().getId(); 81 this.customerId = device.getCustomerId().getId();
78 } 82 }
  83 + if (device.getDeviceProfileId() != null) {
  84 + this.deviceProfileId = device.getDeviceProfileId().getId();
  85 + }
79 this.name = device.getName(); 86 this.name = device.getName();
80 this.type = device.getType(); 87 this.type = device.getType();
81 this.label = device.getLabel(); 88 this.label = device.getLabel();
@@ -87,6 +94,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti @@ -87,6 +94,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
87 this.setCreatedTime(deviceEntity.getCreatedTime()); 94 this.setCreatedTime(deviceEntity.getCreatedTime());
88 this.tenantId = deviceEntity.getTenantId(); 95 this.tenantId = deviceEntity.getTenantId();
89 this.customerId = deviceEntity.getCustomerId(); 96 this.customerId = deviceEntity.getCustomerId();
  97 + this.deviceProfileId = deviceEntity.getDeviceProfileId();
90 this.type = deviceEntity.getType(); 98 this.type = deviceEntity.getType();
91 this.name = deviceEntity.getName(); 99 this.name = deviceEntity.getName();
92 this.label = deviceEntity.getLabel(); 100 this.label = deviceEntity.getLabel();
@@ -113,6 +121,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti @@ -113,6 +121,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
113 if (customerId != null) { 121 if (customerId != null) {
114 device.setCustomerId(new CustomerId(customerId)); 122 device.setCustomerId(new CustomerId(customerId));
115 } 123 }
  124 + if (deviceProfileId != null) {
  125 + device.setDeviceProfileId(new DeviceProfileId(deviceProfileId));
  126 + }
116 device.setName(name); 127 device.setName(name);
117 device.setType(type); 128 device.setType(type);
118 device.setLabel(label); 129 device.setLabel(label);
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.sql;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import lombok.Data;
  20 +import lombok.EqualsAndHashCode;
  21 +import org.hibernate.annotations.Type;
  22 +import org.hibernate.annotations.TypeDef;
  23 +import org.thingsboard.server.common.data.DeviceProfile;
  24 +import org.thingsboard.server.common.data.id.DeviceProfileId;
  25 +import org.thingsboard.server.common.data.id.RuleChainId;
  26 +import org.thingsboard.server.common.data.id.TenantId;
  27 +import org.thingsboard.server.dao.model.BaseSqlEntity;
  28 +import org.thingsboard.server.dao.model.ModelConstants;
  29 +import org.thingsboard.server.dao.model.SearchTextEntity;
  30 +import org.thingsboard.server.dao.util.mapping.JsonStringType;
  31 +
  32 +import javax.persistence.Column;
  33 +import javax.persistence.Entity;
  34 +import javax.persistence.Table;
  35 +import java.util.UUID;
  36 +
  37 +@Data
  38 +@EqualsAndHashCode(callSuper = true)
  39 +@Entity
  40 +@TypeDef(name = "json", typeClass = JsonStringType.class)
  41 +@Table(name = ModelConstants.DEVICE_PROFILE_COLUMN_FAMILY_NAME)
  42 +public final class DeviceProfileEntity extends BaseSqlEntity<DeviceProfile> implements SearchTextEntity<DeviceProfile> {
  43 +
  44 + @Column(name = ModelConstants.DEVICE_PROFILE_TENANT_ID_PROPERTY)
  45 + private UUID tenantId;
  46 +
  47 + @Column(name = ModelConstants.DEVICE_PROFILE_NAME_PROPERTY)
  48 + private String name;
  49 +
  50 + @Column(name = ModelConstants.DEVICE_PROFILE_DESCRIPTION_PROPERTY)
  51 + private String description;
  52 +
  53 + @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
  54 + private String searchText;
  55 +
  56 + @Column(name = ModelConstants.DEVICE_PROFILE_IS_DEFAULT_PROPERTY)
  57 + private boolean isDefault;
  58 +
  59 + @Column(name = ModelConstants.DEVICE_PROFILE_DEFAULT_RULE_CHAIN_ID_PROPERTY, columnDefinition = "uuid")
  60 + private UUID defaultRuleChainId;
  61 +
  62 + @Type(type = "json")
  63 + @Column(name = ModelConstants.DEVICE_PROFILE_PROFILE_DATA_PROPERTY)
  64 + private JsonNode profileData;
  65 +
  66 + public DeviceProfileEntity() {
  67 + super();
  68 + }
  69 +
  70 + public DeviceProfileEntity(DeviceProfile deviceProfile) {
  71 + if (deviceProfile.getId() != null) {
  72 + this.setUuid(deviceProfile.getId().getId());
  73 + }
  74 + if (deviceProfile.getTenantId() != null) {
  75 + this.tenantId = deviceProfile.getTenantId().getId();
  76 + }
  77 + this.setCreatedTime(deviceProfile.getCreatedTime());
  78 + this.name = deviceProfile.getName();
  79 + this.description = deviceProfile.getDescription();
  80 + this.isDefault = deviceProfile.isDefault();
  81 + this.profileData = deviceProfile.getProfileData();
  82 + if (deviceProfile.getDefaultRuleChainId() != null) {
  83 + this.defaultRuleChainId = deviceProfile.getDefaultRuleChainId().getId();
  84 + }
  85 + }
  86 +
  87 + @Override
  88 + public String getSearchTextSource() {
  89 + return name;
  90 + }
  91 +
  92 + @Override
  93 + public void setSearchText(String searchText) {
  94 + this.searchText = searchText;
  95 + }
  96 +
  97 + public String getSearchText() {
  98 + return searchText;
  99 + }
  100 +
  101 + @Override
  102 + public DeviceProfile toData() {
  103 + DeviceProfile deviceProfile = new DeviceProfile(new DeviceProfileId(this.getUuid()));
  104 + deviceProfile.setCreatedTime(createdTime);
  105 + if (tenantId != null) {
  106 + deviceProfile.setTenantId(new TenantId(tenantId));
  107 + }
  108 + deviceProfile.setName(name);
  109 + deviceProfile.setDescription(description);
  110 + deviceProfile.setDefault(isDefault);
  111 + deviceProfile.setProfileData(profileData);
  112 + if (defaultRuleChainId != null) {
  113 + deviceProfile.setDefaultRuleChainId(new RuleChainId(defaultRuleChainId));
  114 + }
  115 + return deviceProfile;
  116 + }
  117 +}
@@ -21,7 +21,9 @@ import lombok.EqualsAndHashCode; @@ -21,7 +21,9 @@ import lombok.EqualsAndHashCode;
21 import org.hibernate.annotations.Type; 21 import org.hibernate.annotations.Type;
22 import org.hibernate.annotations.TypeDef; 22 import org.hibernate.annotations.TypeDef;
23 import org.thingsboard.server.common.data.Tenant; 23 import org.thingsboard.server.common.data.Tenant;
  24 +import org.thingsboard.server.common.data.id.CustomerId;
24 import org.thingsboard.server.common.data.id.TenantId; 25 import org.thingsboard.server.common.data.id.TenantId;
  26 +import org.thingsboard.server.common.data.id.TenantProfileId;
25 import org.thingsboard.server.dao.model.BaseSqlEntity; 27 import org.thingsboard.server.dao.model.BaseSqlEntity;
26 import org.thingsboard.server.dao.model.ModelConstants; 28 import org.thingsboard.server.dao.model.ModelConstants;
27 import org.thingsboard.server.dao.model.SearchTextEntity; 29 import org.thingsboard.server.dao.model.SearchTextEntity;
@@ -30,6 +32,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType; @@ -30,6 +32,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
30 import javax.persistence.Column; 32 import javax.persistence.Column;
31 import javax.persistence.Entity; 33 import javax.persistence.Entity;
32 import javax.persistence.Table; 34 import javax.persistence.Table;
  35 +import java.util.UUID;
33 36
34 @Data 37 @Data
35 @EqualsAndHashCode(callSuper = true) 38 @EqualsAndHashCode(callSuper = true)
@@ -71,16 +74,13 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT @@ -71,16 +74,13 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
71 @Column(name = ModelConstants.EMAIL_PROPERTY) 74 @Column(name = ModelConstants.EMAIL_PROPERTY)
72 private String email; 75 private String email;
73 76
74 - @Column(name = ModelConstants.TENANT_ISOLATED_TB_CORE)  
75 - private boolean isolatedTbCore;  
76 -  
77 - @Column(name = ModelConstants.TENANT_ISOLATED_TB_RULE_ENGINE)  
78 - private boolean isolatedTbRuleEngine;  
79 -  
80 @Type(type = "json") 77 @Type(type = "json")
81 @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY) 78 @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY)
82 private JsonNode additionalInfo; 79 private JsonNode additionalInfo;
83 80
  81 + @Column(name = ModelConstants.TENANT_TENANT_PROFILE_ID_PROPERTY, columnDefinition = "uuid")
  82 + private UUID tenantProfileId;
  83 +
84 public TenantEntity() { 84 public TenantEntity() {
85 super(); 85 super();
86 } 86 }
@@ -101,8 +101,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT @@ -101,8 +101,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
101 this.phone = tenant.getPhone(); 101 this.phone = tenant.getPhone();
102 this.email = tenant.getEmail(); 102 this.email = tenant.getEmail();
103 this.additionalInfo = tenant.getAdditionalInfo(); 103 this.additionalInfo = tenant.getAdditionalInfo();
104 - this.isolatedTbCore = tenant.isIsolatedTbCore();  
105 - this.isolatedTbRuleEngine = tenant.isIsolatedTbRuleEngine(); 104 + if (tenant.getTenantProfileId() != null) {
  105 + this.tenantProfileId = tenant.getTenantProfileId().getId();
  106 + }
106 } 107 }
107 108
108 @Override 109 @Override
@@ -134,8 +135,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT @@ -134,8 +135,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
134 tenant.setPhone(phone); 135 tenant.setPhone(phone);
135 tenant.setEmail(email); 136 tenant.setEmail(email);
136 tenant.setAdditionalInfo(additionalInfo); 137 tenant.setAdditionalInfo(additionalInfo);
137 - tenant.setIsolatedTbCore(isolatedTbCore);  
138 - tenant.setIsolatedTbRuleEngine(isolatedTbRuleEngine); 138 + if (tenantProfileId != null) {
  139 + tenant.setTenantProfileId(new TenantProfileId(tenantProfileId));
  140 + }
139 return tenant; 141 return tenant;
140 } 142 }
141 143
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.model.sql;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +import lombok.Data;
  20 +import lombok.EqualsAndHashCode;
  21 +import org.hibernate.annotations.Type;
  22 +import org.hibernate.annotations.TypeDef;
  23 +import org.thingsboard.server.common.data.TenantProfile;
  24 +import org.thingsboard.server.common.data.id.TenantProfileId;
  25 +import org.thingsboard.server.dao.model.BaseSqlEntity;
  26 +import org.thingsboard.server.dao.model.ModelConstants;
  27 +import org.thingsboard.server.dao.model.SearchTextEntity;
  28 +import org.thingsboard.server.dao.util.mapping.JsonStringType;
  29 +
  30 +import javax.persistence.Column;
  31 +import javax.persistence.Entity;
  32 +import javax.persistence.Table;
  33 +
  34 +@Data
  35 +@EqualsAndHashCode(callSuper = true)
  36 +@Entity
  37 +@TypeDef(name = "json", typeClass = JsonStringType.class)
  38 +@Table(name = ModelConstants.TENANT_PROFILE_COLUMN_FAMILY_NAME)
  39 +public final class TenantProfileEntity extends BaseSqlEntity<TenantProfile> implements SearchTextEntity<TenantProfile> {
  40 +
  41 + @Column(name = ModelConstants.TENANT_PROFILE_NAME_PROPERTY)
  42 + private String name;
  43 +
  44 + @Column(name = ModelConstants.TENANT_PROFILE_DESCRIPTION_PROPERTY)
  45 + private String description;
  46 +
  47 + @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY)
  48 + private String searchText;
  49 +
  50 + @Column(name = ModelConstants.TENANT_PROFILE_IS_DEFAULT_PROPERTY)
  51 + private boolean isDefault;
  52 +
  53 + @Column(name = ModelConstants.TENANT_PROFILE_ISOLATED_TB_CORE)
  54 + private boolean isolatedTbCore;
  55 +
  56 + @Column(name = ModelConstants.TENANT_PROFILE_ISOLATED_TB_RULE_ENGINE)
  57 + private boolean isolatedTbRuleEngine;
  58 +
  59 + @Type(type = "json")
  60 + @Column(name = ModelConstants.TENANT_PROFILE_PROFILE_DATA_PROPERTY)
  61 + private JsonNode profileData;
  62 +
  63 + public TenantProfileEntity() {
  64 + super();
  65 + }
  66 +
  67 + public TenantProfileEntity(TenantProfile tenantProfile) {
  68 + if (tenantProfile.getId() != null) {
  69 + this.setUuid(tenantProfile.getId().getId());
  70 + }
  71 + this.setCreatedTime(tenantProfile.getCreatedTime());
  72 + this.name = tenantProfile.getName();
  73 + this.description = tenantProfile.getDescription();
  74 + this.isDefault = tenantProfile.isDefault();
  75 + this.isolatedTbCore = tenantProfile.isIsolatedTbCore();
  76 + this.isolatedTbRuleEngine = tenantProfile.isIsolatedTbRuleEngine();
  77 + this.profileData = tenantProfile.getProfileData();
  78 + }
  79 +
  80 + @Override
  81 + public String getSearchTextSource() {
  82 + return name;
  83 + }
  84 +
  85 + @Override
  86 + public void setSearchText(String searchText) {
  87 + this.searchText = searchText;
  88 + }
  89 +
  90 + public String getSearchText() {
  91 + return searchText;
  92 + }
  93 +
  94 + @Override
  95 + public TenantProfile toData() {
  96 + TenantProfile tenantProfile = new TenantProfile(new TenantProfileId(this.getUuid()));
  97 + tenantProfile.setCreatedTime(createdTime);
  98 + tenantProfile.setName(name);
  99 + tenantProfile.setDescription(description);
  100 + tenantProfile.setDefault(isDefault);
  101 + tenantProfile.setIsolatedTbCore(isolatedTbCore);
  102 + tenantProfile.setIsolatedTbRuleEngine(isolatedTbRuleEngine);
  103 + tenantProfile.setProfileData(profileData);
  104 + return tenantProfile;
  105 + }
  106 +
  107 +
  108 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.device;
  17 +
  18 +import org.springframework.data.domain.Page;
  19 +import org.springframework.data.domain.Pageable;
  20 +import org.springframework.data.jpa.repository.Query;
  21 +import org.springframework.data.repository.PagingAndSortingRepository;
  22 +import org.springframework.data.repository.query.Param;
  23 +import org.thingsboard.server.common.data.EntityInfo;
  24 +import org.thingsboard.server.dao.model.sql.DeviceProfileEntity;
  25 +
  26 +import java.util.UUID;
  27 +
  28 +public interface DeviceProfileRepository extends PagingAndSortingRepository<DeviceProfileEntity, UUID> {
  29 +
  30 + @Query("SELECT new org.thingsboard.server.common.data.EntityInfo(d.id, 'DEVICE_PROFILE', d.name) " +
  31 + "FROM DeviceProfileEntity d " +
  32 + "WHERE d.id = :deviceProfileId")
  33 + EntityInfo findDeviceProfileInfoById(@Param("deviceProfileId") UUID deviceProfileId);
  34 +
  35 + @Query("SELECT d FROM DeviceProfileEntity d WHERE " +
  36 + "d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
  37 + Page<DeviceProfileEntity> findDeviceProfiles(@Param("tenantId") UUID tenantId,
  38 + @Param("textSearch") String textSearch,
  39 + Pageable pageable);
  40 +
  41 + @Query("SELECT new org.thingsboard.server.common.data.EntityInfo(d.id, 'DEVICE_PROFILE', d.name) " +
  42 + "FROM DeviceProfileEntity d WHERE " +
  43 + "d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
  44 + Page<EntityInfo> findDeviceProfileInfos(@Param("tenantId") UUID tenantId,
  45 + @Param("textSearch") String textSearch,
  46 + Pageable pageable);
  47 +
  48 + @Query("SELECT d FROM DeviceProfileEntity d " +
  49 + "WHERE d.tenantId = :tenantId AND d.isDefault = true")
  50 + DeviceProfileEntity findByDefaultTrueAndTenantId(@Param("tenantId") UUID tenantId);
  51 +
  52 + @Query("SELECT new org.thingsboard.server.common.data.EntityInfo(d.id, 'DEVICE_PROFILE', d.name) " +
  53 + "FROM DeviceProfileEntity d " +
  54 + "WHERE d.tenantId = :tenantId AND d.isDefault = true")
  55 + EntityInfo findDefaultDeviceProfileInfo(@Param("tenantId") UUID tenantId);
  56 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.device;
  17 +
  18 +import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.springframework.stereotype.Component;
  21 +import org.thingsboard.server.common.data.DeviceProfile;
  22 +import org.thingsboard.server.common.data.EntityInfo;
  23 +import org.thingsboard.server.common.data.id.TenantId;
  24 +import org.thingsboard.server.common.data.page.PageData;
  25 +import org.thingsboard.server.common.data.page.PageLink;
  26 +import org.thingsboard.server.dao.DaoUtil;
  27 +import org.thingsboard.server.dao.device.DeviceProfileDao;
  28 +import org.thingsboard.server.dao.model.sql.DeviceProfileEntity;
  29 +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
  30 +
  31 +import java.util.Objects;
  32 +import java.util.UUID;
  33 +
  34 +@Component
  35 +public class JpaDeviceProfileDao extends JpaAbstractSearchTextDao<DeviceProfileEntity, DeviceProfile> implements DeviceProfileDao {
  36 +
  37 + @Autowired
  38 + private DeviceProfileRepository deviceProfileRepository;
  39 +
  40 + @Override
  41 + protected Class<DeviceProfileEntity> getEntityClass() {
  42 + return DeviceProfileEntity.class;
  43 + }
  44 +
  45 + @Override
  46 + protected CrudRepository<DeviceProfileEntity, UUID> getCrudRepository() {
  47 + return deviceProfileRepository;
  48 + }
  49 +
  50 + @Override
  51 + public EntityInfo findDeviceProfileInfoById(TenantId tenantId, UUID deviceProfileId) {
  52 + return deviceProfileRepository.findDeviceProfileInfoById(deviceProfileId);
  53 + }
  54 +
  55 + @Override
  56 + public PageData<DeviceProfile> findDeviceProfiles(TenantId tenantId, PageLink pageLink) {
  57 + return DaoUtil.toPageData(
  58 + deviceProfileRepository.findDeviceProfiles(
  59 + tenantId.getId(),
  60 + Objects.toString(pageLink.getTextSearch(), ""),
  61 + DaoUtil.toPageable(pageLink)));
  62 + }
  63 +
  64 + @Override
  65 + public PageData<EntityInfo> findDeviceProfileInfos(TenantId tenantId, PageLink pageLink) {
  66 + return DaoUtil.pageToPageData(
  67 + deviceProfileRepository.findDeviceProfileInfos(
  68 + tenantId.getId(),
  69 + Objects.toString(pageLink.getTextSearch(), ""),
  70 + DaoUtil.toPageable(pageLink)));
  71 + }
  72 +
  73 + @Override
  74 + public DeviceProfile findDefaultDeviceProfile(TenantId tenantId) {
  75 + return DaoUtil.getData(deviceProfileRepository.findByDefaultTrueAndTenantId(tenantId.getId()));
  76 + }
  77 +
  78 + @Override
  79 + public EntityInfo findDefaultDeviceProfileInfo(TenantId tenantId) {
  80 + return deviceProfileRepository.findDefaultDeviceProfileInfo(tenantId.getId());
  81 + }
  82 +
  83 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.tenant;
  17 +
  18 +import org.springframework.beans.factory.annotation.Autowired;
  19 +import org.springframework.data.repository.CrudRepository;
  20 +import org.springframework.stereotype.Component;
  21 +import org.thingsboard.server.common.data.EntityInfo;
  22 +import org.thingsboard.server.common.data.TenantProfile;
  23 +import org.thingsboard.server.common.data.id.TenantId;
  24 +import org.thingsboard.server.common.data.page.PageData;
  25 +import org.thingsboard.server.common.data.page.PageLink;
  26 +import org.thingsboard.server.dao.DaoUtil;
  27 +import org.thingsboard.server.dao.model.sql.TenantProfileEntity;
  28 +import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
  29 +import org.thingsboard.server.dao.tenant.TenantProfileDao;
  30 +
  31 +import java.util.Objects;
  32 +import java.util.UUID;
  33 +
  34 +@Component
  35 +public class JpaTenantProfileDao extends JpaAbstractSearchTextDao<TenantProfileEntity, TenantProfile> implements TenantProfileDao {
  36 +
  37 + @Autowired
  38 + private TenantProfileRepository tenantProfileRepository;
  39 +
  40 + @Override
  41 + protected Class<TenantProfileEntity> getEntityClass() {
  42 + return TenantProfileEntity.class;
  43 + }
  44 +
  45 + @Override
  46 + protected CrudRepository<TenantProfileEntity, UUID> getCrudRepository() {
  47 + return tenantProfileRepository;
  48 + }
  49 +
  50 + @Override
  51 + public EntityInfo findTenantProfileInfoById(TenantId tenantId, UUID tenantProfileId) {
  52 + return tenantProfileRepository.findTenantProfileInfoById(tenantProfileId);
  53 + }
  54 +
  55 + @Override
  56 + public PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink) {
  57 + return DaoUtil.toPageData(
  58 + tenantProfileRepository.findTenantProfiles(
  59 + Objects.toString(pageLink.getTextSearch(), ""),
  60 + DaoUtil.toPageable(pageLink)));
  61 + }
  62 +
  63 + @Override
  64 + public PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink) {
  65 + return DaoUtil.pageToPageData(
  66 + tenantProfileRepository.findTenantProfileInfos(
  67 + Objects.toString(pageLink.getTextSearch(), ""),
  68 + DaoUtil.toPageable(pageLink)));
  69 + }
  70 +
  71 + @Override
  72 + public TenantProfile findDefaultTenantProfile(TenantId tenantId) {
  73 + return DaoUtil.getData(tenantProfileRepository.findByDefaultTrue());
  74 + }
  75 +
  76 + @Override
  77 + public EntityInfo findDefaultTenantProfileInfo(TenantId tenantId) {
  78 + return tenantProfileRepository.findDefaultTenantProfileInfo();
  79 + }
  80 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.sql.tenant;
  17 +
  18 +import org.springframework.data.domain.Page;
  19 +import org.springframework.data.domain.Pageable;
  20 +import org.springframework.data.jpa.repository.Query;
  21 +import org.springframework.data.repository.PagingAndSortingRepository;
  22 +import org.springframework.data.repository.query.Param;
  23 +import org.thingsboard.server.common.data.EntityInfo;
  24 +import org.thingsboard.server.dao.model.sql.TenantProfileEntity;
  25 +
  26 +import java.util.UUID;
  27 +
  28 +public interface TenantProfileRepository extends PagingAndSortingRepository<TenantProfileEntity, UUID> {
  29 +
  30 + @Query("SELECT new org.thingsboard.server.common.data.EntityInfo(t.id, 'TENANT_PROFILE', t.name) " +
  31 + "FROM TenantProfileEntity t " +
  32 + "WHERE t.id = :tenantProfileId")
  33 + EntityInfo findTenantProfileInfoById(@Param("tenantProfileId") UUID tenantProfileId);
  34 +
  35 + @Query("SELECT t FROM TenantProfileEntity t WHERE " +
  36 + "LOWER(t.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
  37 + Page<TenantProfileEntity> findTenantProfiles(@Param("textSearch") String textSearch,
  38 + Pageable pageable);
  39 +
  40 + @Query("SELECT new org.thingsboard.server.common.data.EntityInfo(t.id, 'TENANT_PROFILE', t.name) " +
  41 + "FROM TenantProfileEntity t " +
  42 + "WHERE LOWER(t.searchText) LIKE LOWER(CONCAT(:textSearch, '%'))")
  43 + Page<EntityInfo> findTenantProfileInfos(@Param("textSearch") String textSearch,
  44 + Pageable pageable);
  45 +
  46 + @Query("SELECT t FROM TenantProfileEntity t " +
  47 + "WHERE t.isDefault = true")
  48 + TenantProfileEntity findByDefaultTrue();
  49 +
  50 + @Query("SELECT new org.thingsboard.server.common.data.EntityInfo(t.id, 'TENANT_PROFILE', t.name) " +
  51 + "FROM TenantProfileEntity t " +
  52 + "WHERE t.isDefault = true")
  53 + EntityInfo findDefaultTenantProfileInfo();
  54 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.tenant;
  17 +
  18 +import org.thingsboard.server.common.data.EntityInfo;
  19 +import org.thingsboard.server.common.data.TenantProfile;
  20 +import org.thingsboard.server.common.data.id.TenantId;
  21 +import org.thingsboard.server.common.data.page.PageData;
  22 +import org.thingsboard.server.common.data.page.PageLink;
  23 +import org.thingsboard.server.dao.Dao;
  24 +
  25 +import java.util.UUID;
  26 +
  27 +public interface TenantProfileDao extends Dao<TenantProfile> {
  28 +
  29 + EntityInfo findTenantProfileInfoById(TenantId tenantId, UUID tenantProfileId);
  30 +
  31 + TenantProfile save(TenantId tenantId, TenantProfile tenantProfile);
  32 +
  33 + PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink);
  34 +
  35 + PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink);
  36 +
  37 + TenantProfile findDefaultTenantProfile(TenantId tenantId);
  38 +
  39 + EntityInfo findDefaultTenantProfileInfo(TenantId tenantId);
  40 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.tenant;
  17 +
  18 +import lombok.extern.slf4j.Slf4j;
  19 +import org.apache.commons.lang3.StringUtils;
  20 +import org.hibernate.exception.ConstraintViolationException;
  21 +import org.springframework.beans.factory.annotation.Autowired;
  22 +import org.springframework.stereotype.Service;
  23 +import org.thingsboard.server.common.data.EntityInfo;
  24 +import org.thingsboard.server.common.data.TenantProfile;
  25 +import org.thingsboard.server.common.data.id.TenantId;
  26 +import org.thingsboard.server.common.data.id.TenantProfileId;
  27 +import org.thingsboard.server.common.data.page.PageData;
  28 +import org.thingsboard.server.common.data.page.PageLink;
  29 +import org.thingsboard.server.dao.entity.AbstractEntityService;
  30 +import org.thingsboard.server.dao.exception.DataValidationException;
  31 +import org.thingsboard.server.dao.service.DataValidator;
  32 +import org.thingsboard.server.dao.service.PaginatedRemover;
  33 +import org.thingsboard.server.dao.service.Validator;
  34 +import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  35 +
  36 +import static org.thingsboard.server.dao.service.Validator.validateId;
  37 +
  38 +@Service
  39 +@Slf4j
  40 +public class TenantProfileServiceImpl extends AbstractEntityService implements TenantProfileService {
  41 +
  42 + private static final String INCORRECT_TENANT_PROFILE_ID = "Incorrect tenantProfileId ";
  43 +
  44 + @Autowired
  45 + private TenantProfileDao tenantProfileDao;
  46 +
  47 + @Override
  48 + public TenantProfile findTenantProfileById(TenantId tenantId, TenantProfileId tenantProfileId) {
  49 + log.trace("Executing findTenantProfileById [{}]", tenantProfileId);
  50 + Validator.validateId(tenantProfileId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
  51 + return tenantProfileDao.findById(tenantId, tenantProfileId.getId());
  52 + }
  53 +
  54 + @Override
  55 + public EntityInfo findTenantProfileInfoById(TenantId tenantId, TenantProfileId tenantProfileId) {
  56 + log.trace("Executing findTenantProfileInfoById [{}]", tenantProfileId);
  57 + Validator.validateId(tenantProfileId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
  58 + return tenantProfileDao.findTenantProfileInfoById(tenantId, tenantProfileId.getId());
  59 + }
  60 +
  61 + @Override
  62 + public TenantProfile saveTenantProfile(TenantId tenantId, TenantProfile tenantProfile) {
  63 + log.trace("Executing saveTenantProfile [{}]", tenantProfile);
  64 + tenantProfileValidator.validate(tenantProfile, (tenantProfile1) -> TenantId.SYS_TENANT_ID);
  65 + TenantProfile savedTenantProfile;
  66 + try {
  67 + savedTenantProfile = tenantProfileDao.save(tenantId, tenantProfile);
  68 + } catch (Exception t) {
  69 + ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
  70 + if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("tenant_profile_name_unq_key")) {
  71 + throw new DataValidationException("Tenant profile with such name already exists!");
  72 + } else {
  73 + throw t;
  74 + }
  75 + }
  76 + return savedTenantProfile;
  77 + }
  78 +
  79 + @Override
  80 + public void deleteTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
  81 + log.trace("Executing deleteTenantProfile [{}]", tenantProfileId);
  82 + validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
  83 + deleteEntityRelations(tenantId, tenantProfileId);
  84 + tenantProfileDao.removeById(tenantId, tenantProfileId.getId());
  85 + }
  86 +
  87 + @Override
  88 + public PageData<TenantProfile> findTenantProfiles(TenantId tenantId, PageLink pageLink) {
  89 + log.trace("Executing findTenantProfiles pageLink [{}]", pageLink);
  90 + Validator.validatePageLink(pageLink);
  91 + return tenantProfileDao.findTenantProfiles(tenantId, pageLink);
  92 + }
  93 +
  94 + @Override
  95 + public PageData<EntityInfo> findTenantProfileInfos(TenantId tenantId, PageLink pageLink) {
  96 + log.trace("Executing findTenantProfileInfos pageLink [{}]", pageLink);
  97 + Validator.validatePageLink(pageLink);
  98 + return tenantProfileDao.findTenantProfileInfos(tenantId, pageLink);
  99 + }
  100 +
  101 + @Override
  102 + public TenantProfile findOrCreateDefaultTenantProfile(TenantId tenantId) {
  103 + log.trace("Executing findOrCreateDefaultTenantProfile");
  104 + TenantProfile defaultTenantProfile = findDefaultTenantProfile(tenantId);
  105 + if (defaultTenantProfile == null) {
  106 + defaultTenantProfile = new TenantProfile();
  107 + defaultTenantProfile.setDefault(true);
  108 + defaultTenantProfile.setName("Default");
  109 + defaultTenantProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
  110 + defaultTenantProfile.setDescription("Default tenant profile");
  111 + defaultTenantProfile.setIsolatedTbCore(false);
  112 + defaultTenantProfile.setIsolatedTbRuleEngine(false);
  113 + defaultTenantProfile = saveTenantProfile(tenantId, defaultTenantProfile);
  114 + }
  115 + return defaultTenantProfile;
  116 + }
  117 +
  118 + @Override
  119 + public TenantProfile findDefaultTenantProfile(TenantId tenantId) {
  120 + log.trace("Executing findDefaultTenantProfile");
  121 + return tenantProfileDao.findDefaultTenantProfile(tenantId);
  122 + }
  123 +
  124 + @Override
  125 + public EntityInfo findDefaultTenantProfileInfo(TenantId tenantId) {
  126 + log.trace("Executing findDefaultTenantProfileInfo");
  127 + return tenantProfileDao.findDefaultTenantProfileInfo(tenantId);
  128 + }
  129 +
  130 + @Override
  131 + public boolean setDefaultTenantProfile(TenantId tenantId, TenantProfileId tenantProfileId) {
  132 + log.trace("Executing setDefaultTenantProfile [{}]", tenantProfileId);
  133 + validateId(tenantId, INCORRECT_TENANT_PROFILE_ID + tenantProfileId);
  134 + TenantProfile tenantProfile = tenantProfileDao.findById(tenantId, tenantProfileId.getId());
  135 + if (!tenantProfile.isDefault()) {
  136 + tenantProfile.setDefault(true);
  137 + TenantProfile previousDefaultTenantProfile = findDefaultTenantProfile(tenantId);
  138 + if (previousDefaultTenantProfile == null) {
  139 + tenantProfileDao.save(tenantId, tenantProfile);
  140 + return true;
  141 + } else if (!previousDefaultTenantProfile.getId().equals(tenantProfile.getId())) {
  142 + previousDefaultTenantProfile.setDefault(false);
  143 + tenantProfileDao.save(tenantId, previousDefaultTenantProfile);
  144 + tenantProfileDao.save(tenantId, tenantProfile);
  145 + return true;
  146 + }
  147 + }
  148 + return false;
  149 + }
  150 +
  151 + @Override
  152 + public void deleteTenantProfiles(TenantId tenantId) {
  153 + log.trace("Executing deleteTenantProfiles");
  154 + tenantProfilesRemover.removeEntities(tenantId, null);
  155 + }
  156 +
  157 + private DataValidator<TenantProfile> tenantProfileValidator =
  158 + new DataValidator<TenantProfile>() {
  159 + @Override
  160 + protected void validateDataImpl(TenantId tenantId, TenantProfile tenantProfile) {
  161 + if (StringUtils.isEmpty(tenantProfile.getName())) {
  162 + throw new DataValidationException("Tenant profile name should be specified!");
  163 + }
  164 + if (tenantProfile.isDefault()) {
  165 + TenantProfile defaultTenantProfile = findDefaultTenantProfile(tenantId);
  166 + if (defaultTenantProfile != null && !defaultTenantProfile.getId().equals(tenantProfile.getId())) {
  167 + throw new DataValidationException("Another default tenant profile is present!");
  168 + }
  169 + }
  170 + }
  171 + };
  172 +
  173 + private PaginatedRemover<String, TenantProfile> tenantProfilesRemover =
  174 + new PaginatedRemover<String, TenantProfile>() {
  175 +
  176 + @Override
  177 + protected PageData<TenantProfile> findEntities(TenantId tenantId, String id, PageLink pageLink) {
  178 + return tenantProfileDao.findTenantProfiles(tenantId, pageLink);
  179 + }
  180 +
  181 + @Override
  182 + protected void removeEntity(TenantId tenantId, TenantProfile entity) {
  183 + deleteTenantProfile(tenantId, new TenantProfileId(entity.getUuidId()));
  184 + }
  185 + };
  186 +
  187 +}
@@ -20,14 +20,18 @@ import lombok.extern.slf4j.Slf4j; @@ -20,14 +20,18 @@ import lombok.extern.slf4j.Slf4j;
20 import org.apache.commons.lang3.StringUtils; 20 import org.apache.commons.lang3.StringUtils;
21 import org.springframework.beans.factory.annotation.Autowired; 21 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.stereotype.Service; 22 import org.springframework.stereotype.Service;
  23 +import org.thingsboard.server.common.data.EntityInfo;
23 import org.thingsboard.server.common.data.Tenant; 24 import org.thingsboard.server.common.data.Tenant;
  25 +import org.thingsboard.server.common.data.TenantProfile;
24 import org.thingsboard.server.common.data.id.EntityId; 26 import org.thingsboard.server.common.data.id.EntityId;
25 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
  28 +import org.thingsboard.server.common.data.id.TenantProfileId;
26 import org.thingsboard.server.common.data.page.PageData; 29 import org.thingsboard.server.common.data.page.PageData;
27 import org.thingsboard.server.common.data.page.PageLink; 30 import org.thingsboard.server.common.data.page.PageLink;
28 import org.thingsboard.server.dao.asset.AssetService; 31 import org.thingsboard.server.dao.asset.AssetService;
29 import org.thingsboard.server.dao.customer.CustomerService; 32 import org.thingsboard.server.dao.customer.CustomerService;
30 import org.thingsboard.server.dao.dashboard.DashboardService; 33 import org.thingsboard.server.dao.dashboard.DashboardService;
  34 +import org.thingsboard.server.dao.device.DeviceProfileService;
31 import org.thingsboard.server.dao.device.DeviceService; 35 import org.thingsboard.server.dao.device.DeviceService;
32 import org.thingsboard.server.dao.entity.AbstractEntityService; 36 import org.thingsboard.server.dao.entity.AbstractEntityService;
33 import org.thingsboard.server.dao.entityview.EntityViewService; 37 import org.thingsboard.server.dao.entityview.EntityViewService;
@@ -52,6 +56,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe @@ -52,6 +56,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
52 private TenantDao tenantDao; 56 private TenantDao tenantDao;
53 57
54 @Autowired 58 @Autowired
  59 + private TenantProfileService tenantProfileService;
  60 +
  61 + @Autowired
55 private UserService userService; 62 private UserService userService;
56 63
57 @Autowired 64 @Autowired
@@ -64,6 +71,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe @@ -64,6 +71,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
64 private DeviceService deviceService; 71 private DeviceService deviceService;
65 72
66 @Autowired 73 @Autowired
  74 + private DeviceProfileService deviceProfileService;
  75 +
  76 + @Autowired
67 private EntityViewService entityViewService; 77 private EntityViewService entityViewService;
68 78
69 @Autowired 79 @Autowired
@@ -93,8 +103,16 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe @@ -93,8 +103,16 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
93 public Tenant saveTenant(Tenant tenant) { 103 public Tenant saveTenant(Tenant tenant) {
94 log.trace("Executing saveTenant [{}]", tenant); 104 log.trace("Executing saveTenant [{}]", tenant);
95 tenant.setRegion(DEFAULT_TENANT_REGION); 105 tenant.setRegion(DEFAULT_TENANT_REGION);
  106 + if (tenant.getTenantProfileId() == null) {
  107 + TenantProfile tenantProfile = this.tenantProfileService.findOrCreateDefaultTenantProfile(TenantId.SYS_TENANT_ID);
  108 + tenant.setTenantProfileId(tenantProfile.getId());
  109 + }
96 tenantValidator.validate(tenant, Tenant::getId); 110 tenantValidator.validate(tenant, Tenant::getId);
97 - return tenantDao.save(tenant.getId(), tenant); 111 + Tenant savedTenant = tenantDao.save(tenant.getId(), tenant);
  112 + if (tenant.getId() == null) {
  113 + deviceProfileService.createDefaultDeviceProfile(savedTenant.getId());
  114 + }
  115 + return savedTenant;
98 } 116 }
99 117
100 @Override 118 @Override
@@ -107,6 +125,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe @@ -107,6 +125,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
107 entityViewService.deleteEntityViewsByTenantId(tenantId); 125 entityViewService.deleteEntityViewsByTenantId(tenantId);
108 assetService.deleteAssetsByTenantId(tenantId); 126 assetService.deleteAssetsByTenantId(tenantId);
109 deviceService.deleteDevicesByTenantId(tenantId); 127 deviceService.deleteDevicesByTenantId(tenantId);
  128 + deviceProfileService.deleteDeviceProfilesByTenantId(tenantId);
110 userService.deleteTenantAdmins(tenantId); 129 userService.deleteTenantAdmins(tenantId);
111 ruleChainService.deleteRuleChainsByTenantId(tenantId); 130 ruleChainService.deleteRuleChainsByTenantId(tenantId);
112 tenantDao.removeById(tenantId, tenantId.getId()); 131 tenantDao.removeById(tenantId, tenantId.getId());
@@ -143,11 +162,13 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe @@ -143,11 +162,13 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
143 Tenant old = tenantDao.findById(TenantId.SYS_TENANT_ID, tenantId.getId()); 162 Tenant old = tenantDao.findById(TenantId.SYS_TENANT_ID, tenantId.getId());
144 if (old == null) { 163 if (old == null) {
145 throw new DataValidationException("Can't update non existing tenant!"); 164 throw new DataValidationException("Can't update non existing tenant!");
146 - } else if (old.isIsolatedTbRuleEngine() != tenant.isIsolatedTbRuleEngine()) { 165 + }
  166 + // TODO: Move validation to tenant profile
  167 + /* else if (old.isIsolatedTbRuleEngine() != tenant.isIsolatedTbRuleEngine()) {
147 throw new DataValidationException("Can't update isolatedTbRuleEngine property!"); 168 throw new DataValidationException("Can't update isolatedTbRuleEngine property!");
148 } else if (old.isIsolatedTbCore() != tenant.isIsolatedTbCore()) { 169 } else if (old.isIsolatedTbCore() != tenant.isIsolatedTbCore()) {
149 throw new DataValidationException("Can't update isolatedTbCore property!"); 170 throw new DataValidationException("Can't update isolatedTbCore property!");
150 - } 171 + } */
151 } 172 }
152 }; 173 };
153 174
@@ -127,6 +127,7 @@ CREATE TABLE IF NOT EXISTS device ( @@ -127,6 +127,7 @@ CREATE TABLE IF NOT EXISTS device (
127 created_time bigint NOT NULL, 127 created_time bigint NOT NULL,
128 additional_info varchar, 128 additional_info varchar,
129 customer_id uuid, 129 customer_id uuid,
  130 + device_profile_id uuid NOT NULL,
130 type varchar(255), 131 type varchar(255),
131 name varchar(255), 132 name varchar(255),
132 label varchar(255), 133 label varchar(255),
@@ -135,6 +136,19 @@ CREATE TABLE IF NOT EXISTS device ( @@ -135,6 +136,19 @@ CREATE TABLE IF NOT EXISTS device (
135 CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name) 136 CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name)
136 ); 137 );
137 138
  139 +CREATE TABLE IF NOT EXISTS device_profile (
  140 + id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY,
  141 + created_time bigint NOT NULL,
  142 + name varchar(255),
  143 + profile_data varchar,
  144 + description varchar,
  145 + search_text varchar(255),
  146 + is_default boolean,
  147 + tenant_id uuid,
  148 + default_rule_chain_id uuid,
  149 + CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name)
  150 +);
  151 +
138 CREATE TABLE IF NOT EXISTS device_credentials ( 152 CREATE TABLE IF NOT EXISTS device_credentials (
139 id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY, 153 id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY,
140 created_time bigint NOT NULL, 154 created_time bigint NOT NULL,
@@ -187,6 +201,7 @@ CREATE TABLE IF NOT EXISTS tenant ( @@ -187,6 +201,7 @@ CREATE TABLE IF NOT EXISTS tenant (
187 id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY, 201 id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY,
188 created_time bigint NOT NULL, 202 created_time bigint NOT NULL,
189 additional_info varchar, 203 additional_info varchar,
  204 + tenant_profile_id uuid NOT NULL,
190 address varchar, 205 address varchar,
191 address2 varchar, 206 address2 varchar,
192 city varchar(255), 207 city varchar(255),
@@ -202,6 +217,19 @@ CREATE TABLE IF NOT EXISTS tenant ( @@ -202,6 +217,19 @@ CREATE TABLE IF NOT EXISTS tenant (
202 isolated_tb_rule_engine boolean 217 isolated_tb_rule_engine boolean
203 ); 218 );
204 219
  220 +CREATE TABLE IF NOT EXISTS tenant_profile (
  221 + id uuid NOT NULL CONSTRAINT tenant_profile_pkey PRIMARY KEY,
  222 + created_time bigint NOT NULL,
  223 + name varchar(255),
  224 + profile_data varchar,
  225 + description varchar,
  226 + search_text varchar(255),
  227 + is_default boolean,
  228 + isolated_tb_core boolean,
  229 + isolated_tb_rule_engine boolean,
  230 + CONSTRAINT tenant_profile_name_unq_key UNIQUE (name)
  231 +);
  232 +
205 CREATE TABLE IF NOT EXISTS user_credentials ( 233 CREATE TABLE IF NOT EXISTS user_credentials (
206 id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, 234 id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY,
207 created_time bigint NOT NULL, 235 created_time bigint NOT NULL,
@@ -144,6 +144,7 @@ CREATE TABLE IF NOT EXISTS device ( @@ -144,6 +144,7 @@ CREATE TABLE IF NOT EXISTS device (
144 created_time bigint NOT NULL, 144 created_time bigint NOT NULL,
145 additional_info varchar, 145 additional_info varchar,
146 customer_id uuid, 146 customer_id uuid,
  147 + device_profile_id uuid NOT NULL,
147 type varchar(255), 148 type varchar(255),
148 name varchar(255), 149 name varchar(255),
149 label varchar(255), 150 label varchar(255),
@@ -152,6 +153,19 @@ CREATE TABLE IF NOT EXISTS device ( @@ -152,6 +153,19 @@ CREATE TABLE IF NOT EXISTS device (
152 CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name) 153 CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name)
153 ); 154 );
154 155
  156 +CREATE TABLE IF NOT EXISTS device_profile (
  157 + id uuid NOT NULL CONSTRAINT device_profile_pkey PRIMARY KEY,
  158 + created_time bigint NOT NULL,
  159 + name varchar(255),
  160 + profile_data varchar,
  161 + description varchar,
  162 + search_text varchar(255),
  163 + is_default boolean,
  164 + tenant_id uuid,
  165 + default_rule_chain_id uuid,
  166 + CONSTRAINT device_profile_name_unq_key UNIQUE (tenant_id, name)
  167 +);
  168 +
155 CREATE TABLE IF NOT EXISTS device_credentials ( 169 CREATE TABLE IF NOT EXISTS device_credentials (
156 id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY, 170 id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY,
157 created_time bigint NOT NULL, 171 created_time bigint NOT NULL,
@@ -211,6 +225,7 @@ CREATE TABLE IF NOT EXISTS tenant ( @@ -211,6 +225,7 @@ CREATE TABLE IF NOT EXISTS tenant (
211 id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY, 225 id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY,
212 created_time bigint NOT NULL, 226 created_time bigint NOT NULL,
213 additional_info varchar, 227 additional_info varchar,
  228 + tenant_profile_id uuid NOT NULL,
214 address varchar, 229 address varchar,
215 address2 varchar, 230 address2 varchar,
216 city varchar(255), 231 city varchar(255),
@@ -226,6 +241,19 @@ CREATE TABLE IF NOT EXISTS tenant ( @@ -226,6 +241,19 @@ CREATE TABLE IF NOT EXISTS tenant (
226 isolated_tb_rule_engine boolean 241 isolated_tb_rule_engine boolean
227 ); 242 );
228 243
  244 +CREATE TABLE IF NOT EXISTS tenant_profile (
  245 + id uuid NOT NULL CONSTRAINT tenant_profile_pkey PRIMARY KEY,
  246 + created_time bigint NOT NULL,
  247 + name varchar(255),
  248 + profile_data varchar,
  249 + description varchar,
  250 + search_text varchar(255),
  251 + is_default boolean,
  252 + isolated_tb_core boolean,
  253 + isolated_tb_rule_engine boolean,
  254 + CONSTRAINT tenant_profile_name_unq_key UNIQUE (name)
  255 +);
  256 +
229 CREATE TABLE IF NOT EXISTS user_credentials ( 257 CREATE TABLE IF NOT EXISTS user_credentials (
230 id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY, 258 id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY,
231 created_time bigint NOT NULL, 259 created_time bigint NOT NULL,
@@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.BaseData; @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.BaseData;
31 import org.thingsboard.server.common.data.EntityType; 31 import org.thingsboard.server.common.data.EntityType;
32 import org.thingsboard.server.common.data.Event; 32 import org.thingsboard.server.common.data.Event;
33 import org.thingsboard.server.common.data.id.EntityId; 33 import org.thingsboard.server.common.data.id.EntityId;
  34 +import org.thingsboard.server.common.data.id.HasId;
34 import org.thingsboard.server.common.data.id.TenantId; 35 import org.thingsboard.server.common.data.id.TenantId;
35 import org.thingsboard.server.common.data.id.UUIDBased; 36 import org.thingsboard.server.common.data.id.UUIDBased;
36 import org.thingsboard.server.dao.alarm.AlarmService; 37 import org.thingsboard.server.dao.alarm.AlarmService;
@@ -41,6 +42,7 @@ import org.thingsboard.server.dao.component.ComponentDescriptorService; @@ -41,6 +42,7 @@ import org.thingsboard.server.dao.component.ComponentDescriptorService;
41 import org.thingsboard.server.dao.customer.CustomerService; 42 import org.thingsboard.server.dao.customer.CustomerService;
42 import org.thingsboard.server.dao.dashboard.DashboardService; 43 import org.thingsboard.server.dao.dashboard.DashboardService;
43 import org.thingsboard.server.dao.device.DeviceCredentialsService; 44 import org.thingsboard.server.dao.device.DeviceCredentialsService;
  45 +import org.thingsboard.server.dao.device.DeviceProfileService;
44 import org.thingsboard.server.dao.device.DeviceService; 46 import org.thingsboard.server.dao.device.DeviceService;
45 import org.thingsboard.server.dao.entity.EntityService; 47 import org.thingsboard.server.dao.entity.EntityService;
46 import org.thingsboard.server.dao.entityview.EntityViewService; 48 import org.thingsboard.server.dao.entityview.EntityViewService;
@@ -48,6 +50,7 @@ import org.thingsboard.server.dao.event.EventService; @@ -48,6 +50,7 @@ import org.thingsboard.server.dao.event.EventService;
48 import org.thingsboard.server.dao.relation.RelationService; 50 import org.thingsboard.server.dao.relation.RelationService;
49 import org.thingsboard.server.dao.rule.RuleChainService; 51 import org.thingsboard.server.dao.rule.RuleChainService;
50 import org.thingsboard.server.dao.settings.AdminSettingsService; 52 import org.thingsboard.server.dao.settings.AdminSettingsService;
  53 +import org.thingsboard.server.dao.tenant.TenantProfileService;
51 import org.thingsboard.server.dao.tenant.TenantService; 54 import org.thingsboard.server.dao.tenant.TenantService;
52 import org.thingsboard.server.dao.timeseries.TimeseriesService; 55 import org.thingsboard.server.dao.timeseries.TimeseriesService;
53 import org.thingsboard.server.dao.user.UserService; 56 import org.thingsboard.server.dao.user.UserService;
@@ -125,7 +128,13 @@ public abstract class AbstractServiceTest { @@ -125,7 +128,13 @@ public abstract class AbstractServiceTest {
125 @Autowired 128 @Autowired
126 private ComponentDescriptorService componentDescriptorService; 129 private ComponentDescriptorService componentDescriptorService;
127 130
128 - class IdComparator<D extends BaseData<? extends UUIDBased>> implements Comparator<D> { 131 + @Autowired
  132 + protected TenantProfileService tenantProfileService;
  133 +
  134 + @Autowired
  135 + protected DeviceProfileService deviceProfileService;
  136 +
  137 + class IdComparator<D extends HasId> implements Comparator<D> {
129 @Override 138 @Override
130 public int compare(D o1, D o2) { 139 public int compare(D o1, D o2) {
131 return o1.getId().getId().compareTo(o2.getId().getId()); 140 return o1.getId().getId().compareTo(o2.getId().getId());
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.service;
  17 +
  18 +import com.datastax.oss.driver.api.core.uuid.Uuids;
  19 +import org.junit.After;
  20 +import org.junit.Assert;
  21 +import org.junit.Before;
  22 +import org.junit.Test;
  23 +import org.thingsboard.server.common.data.DeviceProfile;
  24 +import org.thingsboard.server.common.data.EntityInfo;
  25 +import org.thingsboard.server.common.data.Tenant;
  26 +import org.thingsboard.server.common.data.id.RuleChainId;
  27 +import org.thingsboard.server.common.data.id.TenantId;
  28 +import org.thingsboard.server.common.data.page.PageData;
  29 +import org.thingsboard.server.common.data.page.PageLink;
  30 +import org.thingsboard.server.dao.exception.DataValidationException;
  31 +import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  32 +
  33 +import java.util.ArrayList;
  34 +import java.util.Collections;
  35 +import java.util.List;
  36 +import java.util.stream.Collectors;
  37 +
  38 +public class BaseDeviceProfileServiceTest extends AbstractServiceTest {
  39 +
  40 + private IdComparator<DeviceProfile> idComparator = new IdComparator<>();
  41 + private IdComparator<EntityInfo> deviceProfileInfoIdComparator = new IdComparator<>();
  42 +
  43 + private TenantId tenantId;
  44 +
  45 + @Before
  46 + public void before() {
  47 + Tenant tenant = new Tenant();
  48 + tenant.setTitle("My tenant");
  49 + Tenant savedTenant = tenantService.saveTenant(tenant);
  50 + Assert.assertNotNull(savedTenant);
  51 + tenantId = savedTenant.getId();
  52 + }
  53 +
  54 + @After
  55 + public void after() {
  56 + tenantService.deleteTenant(tenantId);
  57 + }
  58 +
  59 + @Test
  60 + public void testSaveDeviceProfile() {
  61 + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
  62 + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
  63 + Assert.assertNotNull(savedDeviceProfile);
  64 + Assert.assertNotNull(savedDeviceProfile.getId());
  65 + Assert.assertTrue(savedDeviceProfile.getCreatedTime() > 0);
  66 + Assert.assertEquals(deviceProfile.getName(), savedDeviceProfile.getName());
  67 + Assert.assertEquals(deviceProfile.getDescription(), savedDeviceProfile.getDescription());
  68 + Assert.assertEquals(deviceProfile.getProfileData(), savedDeviceProfile.getProfileData());
  69 + Assert.assertEquals(deviceProfile.isDefault(), savedDeviceProfile.isDefault());
  70 + Assert.assertEquals(deviceProfile.getDefaultRuleChainId(), savedDeviceProfile.getDefaultRuleChainId());
  71 + savedDeviceProfile.setName("New device profile");
  72 + deviceProfileService.saveDeviceProfile(savedDeviceProfile);
  73 + DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
  74 + Assert.assertEquals(foundDeviceProfile.getName(), savedDeviceProfile.getName());
  75 +
  76 + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
  77 + }
  78 +
  79 + @Test
  80 + public void testFindDeviceProfileById() {
  81 + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
  82 + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
  83 + DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
  84 + Assert.assertNotNull(foundDeviceProfile);
  85 + Assert.assertEquals(savedDeviceProfile, foundDeviceProfile);
  86 + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
  87 + }
  88 +
  89 + @Test
  90 + public void testFindDeviceProfileInfoById() {
  91 + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
  92 + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
  93 + EntityInfo foundDeviceProfileInfo = deviceProfileService.findDeviceProfileInfoById(tenantId, savedDeviceProfile.getId());
  94 + Assert.assertNotNull(foundDeviceProfileInfo);
  95 + Assert.assertEquals(savedDeviceProfile.getId(), foundDeviceProfileInfo.getId());
  96 + Assert.assertEquals(savedDeviceProfile.getName(), foundDeviceProfileInfo.getName());
  97 + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
  98 + }
  99 +
  100 + @Test
  101 + public void testFindDefaultDeviceProfile() {
  102 + DeviceProfile foundDefaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
  103 + Assert.assertNotNull(foundDefaultDeviceProfile);
  104 + Assert.assertNotNull(foundDefaultDeviceProfile.getId());
  105 + Assert.assertNotNull(foundDefaultDeviceProfile.getName());
  106 + }
  107 +
  108 + @Test
  109 + public void testFindDefaultDeviceProfileInfo() {
  110 + EntityInfo foundDefaultDeviceProfileInfo = deviceProfileService.findDefaultDeviceProfileInfo(tenantId);
  111 + Assert.assertNotNull(foundDefaultDeviceProfileInfo.getId());
  112 + Assert.assertNotNull(foundDefaultDeviceProfileInfo.getName());
  113 + Assert.assertNotNull(foundDefaultDeviceProfileInfo);
  114 + }
  115 +
  116 + @Test
  117 + public void testSetDefaultDeviceProfile() {
  118 + DeviceProfile deviceProfile1 = this.createDeviceProfile("Device Profile 1");
  119 + DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile 2");
  120 +
  121 + DeviceProfile savedDeviceProfile1 = deviceProfileService.saveDeviceProfile(deviceProfile1);
  122 + DeviceProfile savedDeviceProfile2 = deviceProfileService.saveDeviceProfile(deviceProfile2);
  123 +
  124 + boolean result = deviceProfileService.setDefaultDeviceProfile(tenantId, savedDeviceProfile1.getId());
  125 + Assert.assertTrue(result);
  126 + DeviceProfile defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
  127 + Assert.assertNotNull(defaultDeviceProfile);
  128 + Assert.assertEquals(savedDeviceProfile1.getId(), defaultDeviceProfile.getId());
  129 + result = deviceProfileService.setDefaultDeviceProfile(tenantId, savedDeviceProfile2.getId());
  130 + Assert.assertTrue(result);
  131 + defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId);
  132 + Assert.assertNotNull(defaultDeviceProfile);
  133 + Assert.assertEquals(savedDeviceProfile2.getId(), defaultDeviceProfile.getId());
  134 + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile1.getId());
  135 + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile2.getId());
  136 + }
  137 +
  138 + @Test(expected = DataValidationException.class)
  139 + public void testSaveDeviceProfileWithEmptyName() {
  140 + DeviceProfile deviceProfile = new DeviceProfile();
  141 + deviceProfile.setTenantId(tenantId);
  142 + deviceProfileService.saveDeviceProfile(deviceProfile);
  143 + }
  144 +
  145 + @Test(expected = DataValidationException.class)
  146 + public void testSaveDeviceProfileWithSameName() {
  147 + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
  148 + deviceProfileService.saveDeviceProfile(deviceProfile);
  149 + DeviceProfile deviceProfile2 = this.createDeviceProfile("Device Profile");
  150 + deviceProfileService.saveDeviceProfile(deviceProfile2);
  151 + }
  152 +
  153 + @Test
  154 + public void testDeleteDeviceProfile() {
  155 + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile");
  156 + DeviceProfile savedDeviceProfile = deviceProfileService.saveDeviceProfile(deviceProfile);
  157 + deviceProfileService.deleteDeviceProfile(tenantId, savedDeviceProfile.getId());
  158 + DeviceProfile foundDeviceProfile = deviceProfileService.findDeviceProfileById(tenantId, savedDeviceProfile.getId());
  159 + Assert.assertNull(foundDeviceProfile);
  160 + }
  161 +
  162 + @Test
  163 + public void testFindDeviceProfiles() {
  164 +
  165 + List<DeviceProfile> deviceProfiles = new ArrayList<>();
  166 + PageLink pageLink = new PageLink(17);
  167 + PageData<DeviceProfile> pageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
  168 + Assert.assertFalse(pageData.hasNext());
  169 + Assert.assertEquals(1, pageData.getTotalElements());
  170 + deviceProfiles.addAll(pageData.getData());
  171 +
  172 + for (int i=0;i<28;i++) {
  173 + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i);
  174 + deviceProfiles.add(deviceProfileService.saveDeviceProfile(deviceProfile));
  175 + }
  176 +
  177 + List<DeviceProfile> loadedDeviceProfiles = new ArrayList<>();
  178 + pageLink = new PageLink(17);
  179 + do {
  180 + pageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
  181 + loadedDeviceProfiles.addAll(pageData.getData());
  182 + if (pageData.hasNext()) {
  183 + pageLink = pageLink.nextPageLink();
  184 + }
  185 + } while (pageData.hasNext());
  186 +
  187 + Collections.sort(deviceProfiles, idComparator);
  188 + Collections.sort(loadedDeviceProfiles, idComparator);
  189 +
  190 + Assert.assertEquals(deviceProfiles, loadedDeviceProfiles);
  191 +
  192 + for (DeviceProfile deviceProfile : loadedDeviceProfiles) {
  193 + if (!deviceProfile.isDefault()) {
  194 + deviceProfileService.deleteDeviceProfile(tenantId, deviceProfile.getId());
  195 + }
  196 + }
  197 +
  198 + pageLink = new PageLink(17);
  199 + pageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
  200 + Assert.assertFalse(pageData.hasNext());
  201 + Assert.assertEquals(1, pageData.getTotalElements());
  202 + }
  203 +
  204 + @Test
  205 + public void testFindDeviceProfileInfos() {
  206 +
  207 + List<DeviceProfile> deviceProfiles = new ArrayList<>();
  208 + PageLink pageLink = new PageLink(17);
  209 + PageData<DeviceProfile> deviceProfilePageData = deviceProfileService.findDeviceProfiles(tenantId, pageLink);
  210 + Assert.assertFalse(deviceProfilePageData.hasNext());
  211 + Assert.assertEquals(1, deviceProfilePageData.getTotalElements());
  212 + deviceProfiles.addAll(deviceProfilePageData.getData());
  213 +
  214 + for (int i=0;i<28;i++) {
  215 + DeviceProfile deviceProfile = this.createDeviceProfile("Device Profile"+i);
  216 + deviceProfiles.add(deviceProfileService.saveDeviceProfile(deviceProfile));
  217 + }
  218 +
  219 + List<EntityInfo> loadedDeviceProfileInfos = new ArrayList<>();
  220 + pageLink = new PageLink(17);
  221 + PageData<EntityInfo> pageData;
  222 + do {
  223 + pageData = deviceProfileService.findDeviceProfileInfos(tenantId, pageLink);
  224 + loadedDeviceProfileInfos.addAll(pageData.getData());
  225 + if (pageData.hasNext()) {
  226 + pageLink = pageLink.nextPageLink();
  227 + }
  228 + } while (pageData.hasNext());
  229 +
  230 +
  231 + Collections.sort(deviceProfiles, idComparator);
  232 + Collections.sort(loadedDeviceProfileInfos, deviceProfileInfoIdComparator);
  233 +
  234 + List<EntityInfo> deviceProfileInfos = deviceProfiles.stream().map(deviceProfile -> new EntityInfo(deviceProfile.getId(),
  235 + deviceProfile.getName())).collect(Collectors.toList());
  236 +
  237 + Assert.assertEquals(deviceProfileInfos, loadedDeviceProfileInfos);
  238 +
  239 + for (DeviceProfile deviceProfile : deviceProfiles) {
  240 + if (!deviceProfile.isDefault()) {
  241 + deviceProfileService.deleteDeviceProfile(tenantId, deviceProfile.getId());
  242 + }
  243 + }
  244 +
  245 + pageLink = new PageLink(17);
  246 + pageData = deviceProfileService.findDeviceProfileInfos(tenantId, pageLink);
  247 + Assert.assertFalse(pageData.hasNext());
  248 + Assert.assertEquals(1, pageData.getTotalElements());
  249 + }
  250 +
  251 + private DeviceProfile createDeviceProfile(String name) {
  252 + DeviceProfile deviceProfile = new DeviceProfile();
  253 + deviceProfile.setTenantId(tenantId);
  254 + deviceProfile.setName(name);
  255 + deviceProfile.setDescription(name + " Test");
  256 + deviceProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
  257 + deviceProfile.setDefault(false);
  258 + deviceProfile.setDefaultRuleChainId(new RuleChainId(Uuids.timeBased()));
  259 + return deviceProfile;
  260 + }
  261 +
  262 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.service;
  17 +
  18 +import org.junit.After;
  19 +import org.junit.Assert;
  20 +import org.junit.Test;
  21 +import org.thingsboard.server.common.data.EntityInfo;
  22 +import org.thingsboard.server.common.data.TenantProfile;
  23 +import org.thingsboard.server.common.data.id.TenantId;
  24 +import org.thingsboard.server.common.data.id.TenantProfileId;
  25 +import org.thingsboard.server.common.data.page.PageData;
  26 +import org.thingsboard.server.common.data.page.PageLink;
  27 +import org.thingsboard.server.dao.exception.DataValidationException;
  28 +import org.thingsboard.server.dao.util.mapping.JacksonUtil;
  29 +
  30 +import java.util.ArrayList;
  31 +import java.util.Collections;
  32 +import java.util.List;
  33 +import java.util.stream.Collectors;
  34 +
  35 +public class BaseTenantProfileServiceTest extends AbstractServiceTest {
  36 +
  37 + private IdComparator<TenantProfile> idComparator = new IdComparator<>();
  38 + private IdComparator<EntityInfo> tenantProfileInfoIdComparator = new IdComparator<>();
  39 +
  40 + @After
  41 + public void after() {
  42 + tenantProfileService.deleteTenantProfiles(TenantId.SYS_TENANT_ID);
  43 + }
  44 +
  45 + @Test
  46 + public void testSaveTenantProfile() {
  47 + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
  48 + TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  49 + Assert.assertNotNull(savedTenantProfile);
  50 + Assert.assertNotNull(savedTenantProfile.getId());
  51 + Assert.assertTrue(savedTenantProfile.getCreatedTime() > 0);
  52 + Assert.assertEquals(tenantProfile.getName(), savedTenantProfile.getName());
  53 + Assert.assertEquals(tenantProfile.getDescription(), savedTenantProfile.getDescription());
  54 + Assert.assertEquals(tenantProfile.getProfileData(), savedTenantProfile.getProfileData());
  55 + Assert.assertEquals(tenantProfile.isDefault(), savedTenantProfile.isDefault());
  56 + Assert.assertEquals(tenantProfile.isIsolatedTbCore(), savedTenantProfile.isIsolatedTbCore());
  57 + Assert.assertEquals(tenantProfile.isIsolatedTbRuleEngine(), savedTenantProfile.isIsolatedTbRuleEngine());
  58 +
  59 + savedTenantProfile.setName("New tenant profile");
  60 + tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile);
  61 + TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  62 + Assert.assertEquals(foundTenantProfile.getName(), savedTenantProfile.getName());
  63 +
  64 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  65 + }
  66 +
  67 + @Test
  68 + public void testFindTenantProfileById() {
  69 + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
  70 + TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  71 + TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  72 + Assert.assertNotNull(foundTenantProfile);
  73 + Assert.assertEquals(savedTenantProfile, foundTenantProfile);
  74 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  75 + }
  76 +
  77 + @Test
  78 + public void testFindTenantProfileInfoById() {
  79 + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
  80 + TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  81 + EntityInfo foundTenantProfileInfo = tenantProfileService.findTenantProfileInfoById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  82 + Assert.assertNotNull(foundTenantProfileInfo);
  83 + Assert.assertEquals(savedTenantProfile.getId(), foundTenantProfileInfo.getId());
  84 + Assert.assertEquals(savedTenantProfile.getName(), foundTenantProfileInfo.getName());
  85 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  86 + }
  87 +
  88 + @Test
  89 + public void testFindDefaultTenantProfile() {
  90 + TenantProfile tenantProfile = this.createTenantProfile("Default Tenant Profile");
  91 + tenantProfile.setDefault(true);
  92 + TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  93 + TenantProfile foundDefaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
  94 + Assert.assertNotNull(foundDefaultTenantProfile);
  95 + Assert.assertEquals(savedTenantProfile, foundDefaultTenantProfile);
  96 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  97 + }
  98 +
  99 + @Test
  100 + public void testFindDefaultTenantProfileInfo() {
  101 + TenantProfile tenantProfile = this.createTenantProfile("Default Tenant Profile");
  102 + tenantProfile.setDefault(true);
  103 + TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  104 + EntityInfo foundDefaultTenantProfileInfo = tenantProfileService.findDefaultTenantProfileInfo(TenantId.SYS_TENANT_ID);
  105 + Assert.assertNotNull(foundDefaultTenantProfileInfo);
  106 + Assert.assertEquals(savedTenantProfile.getId(), foundDefaultTenantProfileInfo.getId());
  107 + Assert.assertEquals(savedTenantProfile.getName(), foundDefaultTenantProfileInfo.getName());
  108 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  109 + }
  110 +
  111 + @Test
  112 + public void testSetDefaultTenantProfile() {
  113 + TenantProfile tenantProfile1 = this.createTenantProfile("Tenant Profile 1");
  114 + TenantProfile tenantProfile2 = this.createTenantProfile("Tenant Profile 2");
  115 +
  116 + TenantProfile savedTenantProfile1 = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile1);
  117 + TenantProfile savedTenantProfile2 = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile2);
  118 +
  119 + boolean result = tenantProfileService.setDefaultTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile1.getId());
  120 + Assert.assertTrue(result);
  121 + TenantProfile defaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
  122 + Assert.assertNotNull(defaultTenantProfile);
  123 + Assert.assertEquals(savedTenantProfile1.getId(), defaultTenantProfile.getId());
  124 + result = tenantProfileService.setDefaultTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile2.getId());
  125 + Assert.assertTrue(result);
  126 + defaultTenantProfile = tenantProfileService.findDefaultTenantProfile(TenantId.SYS_TENANT_ID);
  127 + Assert.assertNotNull(defaultTenantProfile);
  128 + Assert.assertEquals(savedTenantProfile2.getId(), defaultTenantProfile.getId());
  129 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile1.getId());
  130 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile2.getId());
  131 + }
  132 +
  133 + @Test(expected = DataValidationException.class)
  134 + public void testSaveTenantProfileWithEmptyName() {
  135 + TenantProfile tenantProfile = new TenantProfile();
  136 + tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  137 + }
  138 +
  139 + @Test(expected = DataValidationException.class)
  140 + public void testSaveTenantProfileWithSameName() {
  141 + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
  142 + tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  143 + TenantProfile tenantProfile2 = this.createTenantProfile("Tenant Profile");
  144 + tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile2);
  145 + }
  146 +
  147 + @Test
  148 + public void testDeleteTenantProfile() {
  149 + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile");
  150 + TenantProfile savedTenantProfile = tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile);
  151 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  152 + TenantProfile foundTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenantProfile.getId());
  153 + Assert.assertNull(foundTenantProfile);
  154 + }
  155 +
  156 + @Test
  157 + public void testFindTenantProfiles() {
  158 +
  159 + List<TenantProfile> tenantProfiles = new ArrayList<>();
  160 + PageLink pageLink = new PageLink(17);
  161 + PageData<TenantProfile> pageData = tenantProfileService.findTenantProfiles(TenantId.SYS_TENANT_ID, pageLink);
  162 + Assert.assertFalse(pageData.hasNext());
  163 + Assert.assertTrue(pageData.getData().isEmpty());
  164 + tenantProfiles.addAll(pageData.getData());
  165 +
  166 + for (int i=0;i<28;i++) {
  167 + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile"+i);
  168 + tenantProfiles.add(tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile));
  169 + }
  170 +
  171 + List<TenantProfile> loadedTenantProfiles = new ArrayList<>();
  172 + pageLink = new PageLink(17);
  173 + do {
  174 + pageData = tenantProfileService.findTenantProfiles(TenantId.SYS_TENANT_ID, pageLink);
  175 + loadedTenantProfiles.addAll(pageData.getData());
  176 + if (pageData.hasNext()) {
  177 + pageLink = pageLink.nextPageLink();
  178 + }
  179 + } while (pageData.hasNext());
  180 +
  181 + Collections.sort(tenantProfiles, idComparator);
  182 + Collections.sort(loadedTenantProfiles, idComparator);
  183 +
  184 + Assert.assertEquals(tenantProfiles, loadedTenantProfiles);
  185 +
  186 + for (TenantProfile tenantProfile : loadedTenantProfiles) {
  187 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile.getId());
  188 + }
  189 +
  190 + pageLink = new PageLink(17);
  191 + pageData = tenantProfileService.findTenantProfiles(TenantId.SYS_TENANT_ID, pageLink);
  192 + Assert.assertFalse(pageData.hasNext());
  193 + Assert.assertTrue(pageData.getData().isEmpty());
  194 +
  195 + }
  196 +
  197 + @Test
  198 + public void testFindTenantProfileInfos() {
  199 +
  200 + List<TenantProfile> tenantProfiles = new ArrayList<>();
  201 +
  202 + for (int i=0;i<28;i++) {
  203 + TenantProfile tenantProfile = this.createTenantProfile("Tenant Profile"+i);
  204 + tenantProfiles.add(tenantProfileService.saveTenantProfile(TenantId.SYS_TENANT_ID, tenantProfile));
  205 + }
  206 +
  207 + List<EntityInfo> loadedTenantProfileInfos = new ArrayList<>();
  208 + PageLink pageLink = new PageLink(17);
  209 + PageData<EntityInfo> pageData;
  210 + do {
  211 + pageData = tenantProfileService.findTenantProfileInfos(TenantId.SYS_TENANT_ID, pageLink);
  212 + loadedTenantProfileInfos.addAll(pageData.getData());
  213 + if (pageData.hasNext()) {
  214 + pageLink = pageLink.nextPageLink();
  215 + }
  216 + } while (pageData.hasNext());
  217 +
  218 + Collections.sort(tenantProfiles, idComparator);
  219 + Collections.sort(loadedTenantProfileInfos, tenantProfileInfoIdComparator);
  220 +
  221 + List<EntityInfo> tenantProfileInfos = tenantProfiles.stream().map(tenantProfile -> new EntityInfo(tenantProfile.getId(),
  222 + tenantProfile.getName())).collect(Collectors.toList());
  223 +
  224 + Assert.assertEquals(tenantProfileInfos, loadedTenantProfileInfos);
  225 +
  226 + for (EntityInfo tenantProfile : loadedTenantProfileInfos) {
  227 + tenantProfileService.deleteTenantProfile(TenantId.SYS_TENANT_ID, new TenantProfileId(tenantProfile.getId().getId()));
  228 + }
  229 +
  230 + pageLink = new PageLink(17);
  231 + pageData = tenantProfileService.findTenantProfileInfos(TenantId.SYS_TENANT_ID, pageLink);
  232 + Assert.assertFalse(pageData.hasNext());
  233 + Assert.assertTrue(pageData.getData().isEmpty());
  234 +
  235 + }
  236 +
  237 + private TenantProfile createTenantProfile(String name) {
  238 + TenantProfile tenantProfile = new TenantProfile();
  239 + tenantProfile.setName(name);
  240 + tenantProfile.setDescription(name + " Test");
  241 + tenantProfile.setProfileData(JacksonUtil.OBJECT_MAPPER.createObjectNode());
  242 + tenantProfile.setDefault(false);
  243 + tenantProfile.setIsolatedTbCore(false);
  244 + tenantProfile.setIsolatedTbRuleEngine(false);
  245 + return tenantProfile;
  246 + }
  247 +
  248 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.service.sql;
  17 +
  18 +import org.thingsboard.server.dao.service.BaseDeviceProfileServiceTest;
  19 +import org.thingsboard.server.dao.service.DaoSqlTest;
  20 +
  21 +@DaoSqlTest
  22 +public class DeviceProfileServiceSqlTest extends BaseDeviceProfileServiceTest {
  23 +}
  1 +/**
  2 + * Copyright © 2016-2020 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.service.sql;
  17 +
  18 +import org.thingsboard.server.dao.service.BaseTenantProfileServiceTest;
  19 +import org.thingsboard.server.dao.service.DaoSqlTest;
  20 +
  21 +@DaoSqlTest
  22 +public class TenantProfileServiceSqlTest extends BaseTenantProfileServiceTest {
  23 +}
@@ -20,4 +20,6 @@ DROP TABLE IF EXISTS widgets_bundle; @@ -20,4 +20,6 @@ DROP TABLE IF EXISTS widgets_bundle;
20 DROP TABLE IF EXISTS rule_node; 20 DROP TABLE IF EXISTS rule_node;
21 DROP TABLE IF EXISTS rule_chain; 21 DROP TABLE IF EXISTS rule_chain;
22 DROP TABLE IF EXISTS entity_view; 22 DROP TABLE IF EXISTS entity_view;
  23 +DROP TABLE IF EXISTS device_profile;
  24 +DROP TABLE IF EXISTS tenant_profile;
23 DROP FUNCTION IF EXISTS to_uuid; 25 DROP FUNCTION IF EXISTS to_uuid;
@@ -21,4 +21,6 @@ DROP TABLE IF EXISTS widgets_bundle; @@ -21,4 +21,6 @@ DROP TABLE IF EXISTS widgets_bundle;
21 DROP TABLE IF EXISTS rule_node; 21 DROP TABLE IF EXISTS rule_node;
22 DROP TABLE IF EXISTS rule_chain; 22 DROP TABLE IF EXISTS rule_chain;
23 DROP TABLE IF EXISTS entity_view; 23 DROP TABLE IF EXISTS entity_view;
24 -DROP TABLE IF EXISTS tb_schema_settings;  
  24 +DROP TABLE IF EXISTS device_profile;
  25 +DROP TABLE IF EXISTS tenant_profile;
  26 +DROP TABLE IF EXISTS tb_schema_settings;
@@ -21,4 +21,6 @@ DROP TABLE IF EXISTS widgets_bundle; @@ -21,4 +21,6 @@ DROP TABLE IF EXISTS widgets_bundle;
21 DROP TABLE IF EXISTS rule_node; 21 DROP TABLE IF EXISTS rule_node;
22 DROP TABLE IF EXISTS rule_chain; 22 DROP TABLE IF EXISTS rule_chain;
23 DROP TABLE IF EXISTS entity_view; 23 DROP TABLE IF EXISTS entity_view;
24 -DROP TABLE IF EXISTS tb_schema_settings;  
  24 +DROP TABLE IF EXISTS device_profile;
  25 +DROP TABLE IF EXISTS tenant_profile;
  26 +DROP TABLE IF EXISTS tb_schema_settings;