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 58 import org.thingsboard.server.dao.nosql.CassandraBufferedRateExecutor;
59 59 import org.thingsboard.server.dao.relation.RelationService;
60 60 import org.thingsboard.server.dao.rule.RuleChainService;
  61 +import org.thingsboard.server.dao.tenant.TenantProfileService;
61 62 import org.thingsboard.server.dao.tenant.TenantService;
62 63 import org.thingsboard.server.dao.timeseries.TimeseriesService;
63 64 import org.thingsboard.server.dao.user.UserService;
... ... @@ -139,6 +140,10 @@ public class ActorSystemContext {
139 140
140 141 @Autowired
141 142 @Getter
  143 + private TenantProfileService tenantProfileService;
  144 +
  145 + @Autowired
  146 + @Getter
142 147 private CustomerService customerService;
143 148
144 149 @Autowired
... ...
... ... @@ -27,6 +27,7 @@ import org.thingsboard.server.actors.service.DefaultActorService;
27 27 import org.thingsboard.server.actors.tenant.TenantActor;
28 28 import org.thingsboard.server.common.data.EntityType;
29 29 import org.thingsboard.server.common.data.Tenant;
  30 +import org.thingsboard.server.common.data.TenantProfile;
30 31 import org.thingsboard.server.common.data.id.EntityId;
31 32 import org.thingsboard.server.common.data.id.TenantId;
32 33 import org.thingsboard.server.common.data.page.PageDataIterable;
... ... @@ -116,7 +117,9 @@ public class AppActor extends ContextAwareActor {
116 117 boolean isRuleEngine = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE);
117 118 boolean isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE);
118 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 123 log.debug("[{}] Creating tenant actor", tenant.getId());
121 124 getOrCreateTenantActor(tenant.getId());
122 125 log.debug("[{}] Tenant actor created.", tenant.getId());
... ...
... ... @@ -31,6 +31,7 @@ import org.thingsboard.server.actors.service.ContextBasedCreator;
31 31 import org.thingsboard.server.actors.service.DefaultActorService;
32 32 import org.thingsboard.server.common.data.EntityType;
33 33 import org.thingsboard.server.common.data.Tenant;
  34 +import org.thingsboard.server.common.data.TenantProfile;
34 35 import org.thingsboard.server.common.data.id.DeviceId;
35 36 import org.thingsboard.server.common.data.id.EntityId;
36 37 import org.thingsboard.server.common.data.id.RuleChainId;
... ... @@ -75,12 +76,16 @@ public class TenantActor extends RuleChainManagerActor {
75 76 // This Service may be started for specific tenant only.
76 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 83 isRuleEngineForCurrentTenant = systemContext.getServiceInfoProvider().isService(ServiceType.TB_RULE_ENGINE);
79 84 isCore = systemContext.getServiceInfoProvider().isService(ServiceType.TB_CORE);
80 85
81 86 if (isRuleEngineForCurrentTenant) {
82 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 89 log.info("[{}] Going to init rule chains", tenantId);
85 90 initRuleChains();
86 91 } else {
... ...
... ... @@ -175,6 +175,9 @@ public class ThingsboardInstallService {
175 175 case "3.1.0":
176 176 log.info("Upgrading ThingsBoard from version 3.1.0 to 3.1.1 ...");
177 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 181 log.info("Updating system data...");
179 182 systemDataLoaderService.updateSystemWidgets();
180 183 break;
... ... @@ -206,6 +209,7 @@ public class ThingsboardInstallService {
206 209 componentDiscoveryService.discoverComponents();
207 210
208 211 systemDataLoaderService.createSysAdmin();
  212 + systemDataLoaderService.createDefaultTenantProfile();
209 213 systemDataLoaderService.createAdminSettings();
210 214 systemDataLoaderService.loadSystemWidgets();
211 215 // systemDataLoaderService.loadSystemPlugins();
... ...
... ... @@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.Customer;
28 28 import org.thingsboard.server.common.data.DataConstants;
29 29 import org.thingsboard.server.common.data.Device;
30 30 import org.thingsboard.server.common.data.Tenant;
  31 +import org.thingsboard.server.common.data.TenantProfile;
31 32 import org.thingsboard.server.common.data.User;
32 33 import org.thingsboard.server.common.data.asset.Asset;
33 34 import org.thingsboard.server.common.data.id.CustomerId;
... ... @@ -49,6 +50,7 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService;
49 50 import org.thingsboard.server.dao.device.DeviceService;
50 51 import org.thingsboard.server.dao.relation.RelationService;
51 52 import org.thingsboard.server.dao.settings.AdminSettingsService;
  53 +import org.thingsboard.server.dao.tenant.TenantProfileService;
52 54 import org.thingsboard.server.dao.tenant.TenantService;
53 55 import org.thingsboard.server.dao.user.UserService;
54 56 import org.thingsboard.server.dao.widget.WidgetsBundleService;
... ... @@ -83,6 +85,9 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
83 85 private TenantService tenantService;
84 86
85 87 @Autowired
  88 + private TenantProfileService tenantProfileService;
  89 +
  90 + @Autowired
86 91 private CustomerService customerService;
87 92
88 93 @Autowired
... ... @@ -111,6 +116,11 @@ public class DefaultSystemDataLoaderService implements SystemDataLoaderService {
111 116 }
112 117
113 118 @Override
  119 + public void createDefaultTenantProfile() throws Exception {
  120 + tenantProfileService.findOrCreateDefaultTenantProfile(TenantId.SYS_TENANT_ID);
  121 + }
  122 +
  123 + @Override
114 124 public void createAdminSettings() throws Exception {
115 125 AdminSettings generalSettings = new AdminSettings();
116 126 generalSettings.setKey("general");
... ...
... ... @@ -303,6 +303,14 @@ public class SqlDatabaseUpgradeService implements DatabaseEntitiesUpgradeService
303 303 log.info("Schema updated.");
304 304 }
305 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 314 default:
307 315 throw new RuntimeException("Unable to upgrade SQL database, unsupported fromVersion: " + fromVersion);
308 316 }
... ...
... ... @@ -19,6 +19,8 @@ public interface SystemDataLoaderService {
19 19
20 20 void createSysAdmin() throws Exception;
21 21
  22 + void createDefaultTenantProfile() throws Exception;
  23 +
22 24 void createAdminSettings() throws Exception;
23 25
24 26 void loadSystemWidgets() throws Exception;
... ...
... ... @@ -19,7 +19,9 @@ import lombok.extern.slf4j.Slf4j;
19 19 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
20 20 import org.springframework.stereotype.Service;
21 21 import org.thingsboard.server.common.data.Tenant;
  22 +import org.thingsboard.server.common.data.TenantProfile;
22 23 import org.thingsboard.server.common.data.id.TenantId;
  24 +import org.thingsboard.server.dao.tenant.TenantProfileService;
23 25 import org.thingsboard.server.dao.tenant.TenantService;
24 26 import org.thingsboard.server.queue.discovery.TenantRoutingInfo;
25 27 import org.thingsboard.server.queue.discovery.TenantRoutingInfoService;
... ... @@ -31,15 +33,20 @@ public class DefaultTenantRoutingInfoService implements TenantRoutingInfoService
31 33
32 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 39 this.tenantService = tenantService;
  40 + this.tenantProfileService = tenantProfileService;
36 41 }
37 42
38 43 @Override
39 44 public TenantRoutingInfo getRoutingInfo(TenantId tenantId) {
40 45 Tenant tenant = tenantService.findTenantById(tenantId);
41 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 50 } else {
44 51 throw new RuntimeException("Tenant not found!");
45 52 }
... ...
... ... @@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
28 28 import org.thingsboard.server.common.data.DataConstants;
29 29 import org.thingsboard.server.common.data.Device;
30 30 import org.thingsboard.server.common.data.Tenant;
  31 +import org.thingsboard.server.common.data.TenantProfile;
31 32 import org.thingsboard.server.common.data.id.CustomerId;
32 33 import org.thingsboard.server.common.data.id.DeviceId;
33 34 import org.thingsboard.server.common.data.id.TenantId;
... ... @@ -40,6 +41,7 @@ import org.thingsboard.server.common.msg.TbMsgMetaData;
40 41 import org.thingsboard.server.dao.device.DeviceCredentialsService;
41 42 import org.thingsboard.server.dao.device.DeviceService;
42 43 import org.thingsboard.server.dao.relation.RelationService;
  44 +import org.thingsboard.server.dao.tenant.TenantProfileService;
43 45 import org.thingsboard.server.dao.tenant.TenantService;
44 46 import org.thingsboard.server.gen.transport.TransportProtos.DeviceInfoProto;
45 47 import org.thingsboard.server.gen.transport.TransportProtos.GetOrCreateDeviceFromGatewayRequestMsg;
... ... @@ -78,6 +80,9 @@ public class DefaultTransportApiService implements TransportApiService {
78 80 private TenantService tenantService;
79 81
80 82 @Autowired
  83 + private TenantProfileService tenantProfileService;
  84 +
  85 + @Autowired
81 86 private DeviceService deviceService;
82 87
83 88 @Autowired
... ... @@ -168,10 +173,13 @@ public class DefaultTransportApiService implements TransportApiService {
168 173
169 174 private ListenableFuture<TransportApiResponseMsg> handle(GetTenantRoutingInfoRequestMsg requestMsg) {
170 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 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 18 import lombok.EqualsAndHashCode;
19 19 import org.thingsboard.server.common.data.id.CustomerId;
20 20 import org.thingsboard.server.common.data.id.DeviceId;
  21 +import org.thingsboard.server.common.data.id.DeviceProfileId;
21 22 import org.thingsboard.server.common.data.id.TenantId;
22 23
23 24 @EqualsAndHashCode(callSuper = true)
... ... @@ -30,6 +31,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
30 31 private String name;
31 32 private String type;
32 33 private String label;
  34 + private DeviceProfileId deviceProfileId;
33 35
34 36 public Device() {
35 37 super();
... ... @@ -46,6 +48,7 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
46 48 this.name = device.getName();
47 49 this.type = device.getType();
48 50 this.label = device.getLabel();
  51 + this.deviceProfileId = device.getDeviceProfileId();
49 52 }
50 53
51 54 public TenantId getTenantId() {
... ... @@ -89,6 +92,14 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
89 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 103 @Override
93 104 public String getSearchText() {
94 105 return getName();
... ... @@ -107,6 +118,8 @@ public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implemen
107 118 builder.append(type);
108 119 builder.append(", label=");
109 120 builder.append(label);
  121 + builder.append(", deviceProfileId=");
  122 + builder.append(deviceProfileId);
110 123 builder.append(", additionalInfo=");
111 124 builder.append(getAdditionalInfo());
112 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 19 * @author Andrew Shvayka
20 20 */
21 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 19 import com.fasterxml.jackson.annotation.JsonProperty;
20 20 import lombok.EqualsAndHashCode;
21 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 24 @EqualsAndHashCode(callSuper = true)
26 25 public class Tenant extends ContactBased<TenantId> implements HasTenantId {
... ... @@ -29,8 +28,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
29 28
30 29 private String title;
31 30 private String region;
32   - private boolean isolatedTbCore;
33   - private boolean isolatedTbRuleEngine;
  31 + private TenantProfileId tenantProfileId;
34 32
35 33 public Tenant() {
36 34 super();
... ... @@ -44,6 +42,7 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
44 42 super(tenant);
45 43 this.title = tenant.getTitle();
46 44 this.region = tenant.getRegion();
  45 + this.tenantProfileId = tenant.getTenantProfileId();
47 46 }
48 47
49 48 public String getTitle() {
... ... @@ -74,20 +73,12 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
74 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 84 @Override
... ... @@ -102,10 +93,8 @@ public class Tenant extends ContactBased<TenantId> implements HasTenantId {
102 93 builder.append(title);
103 94 builder.append(", region=");
104 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 98 builder.append(", additionalInfo=");
110 99 builder.append(getAdditionalInfo());
111 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 29
30 30 @JsonDeserialize(using = EntityIdDeserializer.class)
31 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 34 UUID NULL_UUID = UUID.fromString("13814000-1dd2-11b2-8080-808080808080");
35 35
... ...
... ... @@ -62,6 +62,10 @@ public class EntityIdFactory {
62 62 return new WidgetsBundleId(uuid);
63 63 case WIDGET_TYPE:
64 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 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 20 import java.io.Serializable;
21 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 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 18 import java.io.Serializable;
19 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 23 private static final long serialVersionUID = 1L;
24 24
... ...
... ... @@ -43,6 +43,10 @@ public abstract class DaoUtil {
43 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 50 public static Pageable toPageable(PageLink pageLink) {
47 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 34 import org.thingsboard.server.common.data.Customer;
35 35 import org.thingsboard.server.common.data.Device;
36 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 39 import org.thingsboard.server.common.data.EntitySubtype;
38 40 import org.thingsboard.server.common.data.EntityType;
39 41 import org.thingsboard.server.common.data.EntityView;
... ... @@ -41,6 +43,7 @@ import org.thingsboard.server.common.data.Tenant;
41 43 import org.thingsboard.server.common.data.device.DeviceSearchQuery;
42 44 import org.thingsboard.server.common.data.id.CustomerId;
43 45 import org.thingsboard.server.common.data.id.DeviceId;
  46 +import org.thingsboard.server.common.data.id.DeviceProfileId;
44 47 import org.thingsboard.server.common.data.id.EntityId;
45 48 import org.thingsboard.server.common.data.id.TenantId;
46 49 import org.thingsboard.server.common.data.page.PageData;
... ... @@ -96,6 +99,9 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
96 99 private DeviceCredentialsService deviceCredentialsService;
97 100
98 101 @Autowired
  102 + private DeviceProfileService deviceProfileService;
  103 +
  104 + @Autowired
99 105 private EntityViewService entityViewService;
100 106
101 107 @Autowired
... ... @@ -159,6 +165,10 @@ public class DeviceServiceImpl extends AbstractEntityService implements DeviceSe
159 165 deviceValidator.validate(device, Device::getTenantId);
160 166 Device savedDevice;
161 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 172 savedDevice = deviceDao.save(device.getTenantId(), device);
163 173 } catch (Exception t) {
164 174 ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
... ...
... ... @@ -114,12 +114,22 @@ public class ModelConstants {
114 114 public static final String TENANT_TITLE_PROPERTY = TITLE_PROPERTY;
115 115 public static final String TENANT_REGION_PROPERTY = "region";
116 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 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 133 * Cassandra customer constants.
124 134 */
125 135 public static final String CUSTOMER_COLUMN_FAMILY_NAME = "customer";
... ... @@ -141,6 +151,7 @@ public class ModelConstants {
141 151 public static final String DEVICE_TYPE_PROPERTY = "type";
142 152 public static final String DEVICE_LABEL_PROPERTY = "label";
143 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 155 public static final String DEVICE_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME = "device_by_tenant_and_search_text";
145 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 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 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 174 * Cassandra entityView constants.
153 175 */
154 176 public static final String ENTITY_VIEW_TABLE_FAMILY_NAME = "entity_view";
... ...
... ... @@ -23,6 +23,7 @@ import org.hibernate.annotations.TypeDef;
23 23 import org.thingsboard.server.common.data.Device;
24 24 import org.thingsboard.server.common.data.id.CustomerId;
25 25 import org.thingsboard.server.common.data.id.DeviceId;
  26 +import org.thingsboard.server.common.data.id.DeviceProfileId;
26 27 import org.thingsboard.server.common.data.id.TenantId;
27 28 import org.thingsboard.server.dao.model.BaseSqlEntity;
28 29 import org.thingsboard.server.dao.model.ModelConstants;
... ... @@ -61,6 +62,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
61 62 @Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY)
62 63 private JsonNode additionalInfo;
63 64
  65 + @Column(name = ModelConstants.DEVICE_DEVICE_PROFILE_ID_PROPERTY, columnDefinition = "uuid")
  66 + private UUID deviceProfileId;
  67 +
64 68 public AbstractDeviceEntity() {
65 69 super();
66 70 }
... ... @@ -76,6 +80,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
76 80 if (device.getCustomerId() != null) {
77 81 this.customerId = device.getCustomerId().getId();
78 82 }
  83 + if (device.getDeviceProfileId() != null) {
  84 + this.deviceProfileId = device.getDeviceProfileId().getId();
  85 + }
79 86 this.name = device.getName();
80 87 this.type = device.getType();
81 88 this.label = device.getLabel();
... ... @@ -87,6 +94,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
87 94 this.setCreatedTime(deviceEntity.getCreatedTime());
88 95 this.tenantId = deviceEntity.getTenantId();
89 96 this.customerId = deviceEntity.getCustomerId();
  97 + this.deviceProfileId = deviceEntity.getDeviceProfileId();
90 98 this.type = deviceEntity.getType();
91 99 this.name = deviceEntity.getName();
92 100 this.label = deviceEntity.getLabel();
... ... @@ -113,6 +121,9 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
113 121 if (customerId != null) {
114 122 device.setCustomerId(new CustomerId(customerId));
115 123 }
  124 + if (deviceProfileId != null) {
  125 + device.setDeviceProfileId(new DeviceProfileId(deviceProfileId));
  126 + }
116 127 device.setName(name);
117 128 device.setType(type);
118 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 21 import org.hibernate.annotations.Type;
22 22 import org.hibernate.annotations.TypeDef;
23 23 import org.thingsboard.server.common.data.Tenant;
  24 +import org.thingsboard.server.common.data.id.CustomerId;
24 25 import org.thingsboard.server.common.data.id.TenantId;
  26 +import org.thingsboard.server.common.data.id.TenantProfileId;
25 27 import org.thingsboard.server.dao.model.BaseSqlEntity;
26 28 import org.thingsboard.server.dao.model.ModelConstants;
27 29 import org.thingsboard.server.dao.model.SearchTextEntity;
... ... @@ -30,6 +32,7 @@ import org.thingsboard.server.dao.util.mapping.JsonStringType;
30 32 import javax.persistence.Column;
31 33 import javax.persistence.Entity;
32 34 import javax.persistence.Table;
  35 +import java.util.UUID;
33 36
34 37 @Data
35 38 @EqualsAndHashCode(callSuper = true)
... ... @@ -71,16 +74,13 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
71 74 @Column(name = ModelConstants.EMAIL_PROPERTY)
72 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 77 @Type(type = "json")
81 78 @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY)
82 79 private JsonNode additionalInfo;
83 80
  81 + @Column(name = ModelConstants.TENANT_TENANT_PROFILE_ID_PROPERTY, columnDefinition = "uuid")
  82 + private UUID tenantProfileId;
  83 +
84 84 public TenantEntity() {
85 85 super();
86 86 }
... ... @@ -101,8 +101,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
101 101 this.phone = tenant.getPhone();
102 102 this.email = tenant.getEmail();
103 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 109 @Override
... ... @@ -134,8 +135,9 @@ public final class TenantEntity extends BaseSqlEntity<Tenant> implements SearchT
134 135 tenant.setPhone(phone);
135 136 tenant.setEmail(email);
136 137 tenant.setAdditionalInfo(additionalInfo);
137   - tenant.setIsolatedTbCore(isolatedTbCore);
138   - tenant.setIsolatedTbRuleEngine(isolatedTbRuleEngine);
  138 + if (tenantProfileId != null) {
  139 + tenant.setTenantProfileId(new TenantProfileId(tenantProfileId));
  140 + }
139 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 20 import org.apache.commons.lang3.StringUtils;
21 21 import org.springframework.beans.factory.annotation.Autowired;
22 22 import org.springframework.stereotype.Service;
  23 +import org.thingsboard.server.common.data.EntityInfo;
23 24 import org.thingsboard.server.common.data.Tenant;
  25 +import org.thingsboard.server.common.data.TenantProfile;
24 26 import org.thingsboard.server.common.data.id.EntityId;
25 27 import org.thingsboard.server.common.data.id.TenantId;
  28 +import org.thingsboard.server.common.data.id.TenantProfileId;
26 29 import org.thingsboard.server.common.data.page.PageData;
27 30 import org.thingsboard.server.common.data.page.PageLink;
28 31 import org.thingsboard.server.dao.asset.AssetService;
29 32 import org.thingsboard.server.dao.customer.CustomerService;
30 33 import org.thingsboard.server.dao.dashboard.DashboardService;
  34 +import org.thingsboard.server.dao.device.DeviceProfileService;
31 35 import org.thingsboard.server.dao.device.DeviceService;
32 36 import org.thingsboard.server.dao.entity.AbstractEntityService;
33 37 import org.thingsboard.server.dao.entityview.EntityViewService;
... ... @@ -52,6 +56,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
52 56 private TenantDao tenantDao;
53 57
54 58 @Autowired
  59 + private TenantProfileService tenantProfileService;
  60 +
  61 + @Autowired
55 62 private UserService userService;
56 63
57 64 @Autowired
... ... @@ -64,6 +71,9 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
64 71 private DeviceService deviceService;
65 72
66 73 @Autowired
  74 + private DeviceProfileService deviceProfileService;
  75 +
  76 + @Autowired
67 77 private EntityViewService entityViewService;
68 78
69 79 @Autowired
... ... @@ -93,8 +103,16 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
93 103 public Tenant saveTenant(Tenant tenant) {
94 104 log.trace("Executing saveTenant [{}]", tenant);
95 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 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 118 @Override
... ... @@ -107,6 +125,7 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
107 125 entityViewService.deleteEntityViewsByTenantId(tenantId);
108 126 assetService.deleteAssetsByTenantId(tenantId);
109 127 deviceService.deleteDevicesByTenantId(tenantId);
  128 + deviceProfileService.deleteDeviceProfilesByTenantId(tenantId);
110 129 userService.deleteTenantAdmins(tenantId);
111 130 ruleChainService.deleteRuleChainsByTenantId(tenantId);
112 131 tenantDao.removeById(tenantId, tenantId.getId());
... ... @@ -143,11 +162,13 @@ public class TenantServiceImpl extends AbstractEntityService implements TenantSe
143 162 Tenant old = tenantDao.findById(TenantId.SYS_TENANT_ID, tenantId.getId());
144 163 if (old == null) {
145 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 168 throw new DataValidationException("Can't update isolatedTbRuleEngine property!");
148 169 } else if (old.isIsolatedTbCore() != tenant.isIsolatedTbCore()) {
149 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 127 created_time bigint NOT NULL,
128 128 additional_info varchar,
129 129 customer_id uuid,
  130 + device_profile_id uuid NOT NULL,
130 131 type varchar(255),
131 132 name varchar(255),
132 133 label varchar(255),
... ... @@ -135,6 +136,19 @@ CREATE TABLE IF NOT EXISTS device (
135 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 152 CREATE TABLE IF NOT EXISTS device_credentials (
139 153 id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY,
140 154 created_time bigint NOT NULL,
... ... @@ -187,6 +201,7 @@ CREATE TABLE IF NOT EXISTS tenant (
187 201 id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY,
188 202 created_time bigint NOT NULL,
189 203 additional_info varchar,
  204 + tenant_profile_id uuid NOT NULL,
190 205 address varchar,
191 206 address2 varchar,
192 207 city varchar(255),
... ... @@ -202,6 +217,19 @@ CREATE TABLE IF NOT EXISTS tenant (
202 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 233 CREATE TABLE IF NOT EXISTS user_credentials (
206 234 id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY,
207 235 created_time bigint NOT NULL,
... ...
... ... @@ -144,6 +144,7 @@ CREATE TABLE IF NOT EXISTS device (
144 144 created_time bigint NOT NULL,
145 145 additional_info varchar,
146 146 customer_id uuid,
  147 + device_profile_id uuid NOT NULL,
147 148 type varchar(255),
148 149 name varchar(255),
149 150 label varchar(255),
... ... @@ -152,6 +153,19 @@ CREATE TABLE IF NOT EXISTS device (
152 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 169 CREATE TABLE IF NOT EXISTS device_credentials (
156 170 id uuid NOT NULL CONSTRAINT device_credentials_pkey PRIMARY KEY,
157 171 created_time bigint NOT NULL,
... ... @@ -211,6 +225,7 @@ CREATE TABLE IF NOT EXISTS tenant (
211 225 id uuid NOT NULL CONSTRAINT tenant_pkey PRIMARY KEY,
212 226 created_time bigint NOT NULL,
213 227 additional_info varchar,
  228 + tenant_profile_id uuid NOT NULL,
214 229 address varchar,
215 230 address2 varchar,
216 231 city varchar(255),
... ... @@ -226,6 +241,19 @@ CREATE TABLE IF NOT EXISTS tenant (
226 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 257 CREATE TABLE IF NOT EXISTS user_credentials (
230 258 id uuid NOT NULL CONSTRAINT user_credentials_pkey PRIMARY KEY,
231 259 created_time bigint NOT NULL,
... ...
... ... @@ -31,6 +31,7 @@ import org.thingsboard.server.common.data.BaseData;
31 31 import org.thingsboard.server.common.data.EntityType;
32 32 import org.thingsboard.server.common.data.Event;
33 33 import org.thingsboard.server.common.data.id.EntityId;
  34 +import org.thingsboard.server.common.data.id.HasId;
34 35 import org.thingsboard.server.common.data.id.TenantId;
35 36 import org.thingsboard.server.common.data.id.UUIDBased;
36 37 import org.thingsboard.server.dao.alarm.AlarmService;
... ... @@ -41,6 +42,7 @@ import org.thingsboard.server.dao.component.ComponentDescriptorService;
41 42 import org.thingsboard.server.dao.customer.CustomerService;
42 43 import org.thingsboard.server.dao.dashboard.DashboardService;
43 44 import org.thingsboard.server.dao.device.DeviceCredentialsService;
  45 +import org.thingsboard.server.dao.device.DeviceProfileService;
44 46 import org.thingsboard.server.dao.device.DeviceService;
45 47 import org.thingsboard.server.dao.entity.EntityService;
46 48 import org.thingsboard.server.dao.entityview.EntityViewService;
... ... @@ -48,6 +50,7 @@ import org.thingsboard.server.dao.event.EventService;
48 50 import org.thingsboard.server.dao.relation.RelationService;
49 51 import org.thingsboard.server.dao.rule.RuleChainService;
50 52 import org.thingsboard.server.dao.settings.AdminSettingsService;
  53 +import org.thingsboard.server.dao.tenant.TenantProfileService;
51 54 import org.thingsboard.server.dao.tenant.TenantService;
52 55 import org.thingsboard.server.dao.timeseries.TimeseriesService;
53 56 import org.thingsboard.server.dao.user.UserService;
... ... @@ -125,7 +128,13 @@ public abstract class AbstractServiceTest {
125 128 @Autowired
126 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 138 @Override
130 139 public int compare(D o1, D o2) {
131 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 20 DROP TABLE IF EXISTS rule_node;
21 21 DROP TABLE IF EXISTS rule_chain;
22 22 DROP TABLE IF EXISTS entity_view;
  23 +DROP TABLE IF EXISTS device_profile;
  24 +DROP TABLE IF EXISTS tenant_profile;
23 25 DROP FUNCTION IF EXISTS to_uuid;
... ...
... ... @@ -21,4 +21,6 @@ DROP TABLE IF EXISTS widgets_bundle;
21 21 DROP TABLE IF EXISTS rule_node;
22 22 DROP TABLE IF EXISTS rule_chain;
23 23 DROP TABLE IF EXISTS entity_view;
24   -DROP TABLE IF EXISTS tb_schema_settings;
\ No newline at end of file
  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 21 DROP TABLE IF EXISTS rule_node;
22 22 DROP TABLE IF EXISTS rule_chain;
23 23 DROP TABLE IF EXISTS entity_view;
24   -DROP TABLE IF EXISTS tb_schema_settings;
\ No newline at end of file
  24 +DROP TABLE IF EXISTS device_profile;
  25 +DROP TABLE IF EXISTS tenant_profile;
  26 +DROP TABLE IF EXISTS tb_schema_settings;
... ...