Commit f747c8280cbe726a38a158d304ffba8d7f2a5ce9

Authored by Viacheslav Klimov
1 parent cd23b85b

Fix and refactor bulk importing

@@ -17,78 +17,69 @@ package org.thingsboard.server.service.asset; @@ -17,78 +17,69 @@ package org.thingsboard.server.service.asset;
17 17
18 import com.fasterxml.jackson.databind.node.ObjectNode; 18 import com.fasterxml.jackson.databind.node.ObjectNode;
19 import com.fasterxml.jackson.databind.node.TextNode; 19 import com.fasterxml.jackson.databind.node.TextNode;
  20 +import lombok.RequiredArgsConstructor;
20 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
21 import org.thingsboard.common.util.JacksonUtil; 22 import org.thingsboard.common.util.JacksonUtil;
22 -import org.thingsboard.server.cluster.TbClusterService; 23 +import org.thingsboard.server.common.data.EntityType;
23 import org.thingsboard.server.common.data.asset.Asset; 24 import org.thingsboard.server.common.data.asset.Asset;
  25 +import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.dao.asset.AssetService; 26 import org.thingsboard.server.dao.asset.AssetService;
25 -import org.thingsboard.server.dao.tenant.TbTenantProfileCache;  
26 import org.thingsboard.server.queue.util.TbCoreComponent; 27 import org.thingsboard.server.queue.util.TbCoreComponent;
27 -import org.thingsboard.server.service.action.EntityActionService;  
28 import org.thingsboard.server.service.importing.AbstractBulkImportService; 28 import org.thingsboard.server.service.importing.AbstractBulkImportService;
29 import org.thingsboard.server.service.importing.BulkImportColumnType; 29 import org.thingsboard.server.service.importing.BulkImportColumnType;
30 -import org.thingsboard.server.service.importing.BulkImportRequest;  
31 -import org.thingsboard.server.service.importing.ImportedEntityInfo;  
32 -import org.thingsboard.server.service.security.AccessValidator;  
33 import org.thingsboard.server.service.security.model.SecurityUser; 30 import org.thingsboard.server.service.security.model.SecurityUser;
34 -import org.thingsboard.server.service.security.permission.AccessControlService;  
35 -import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;  
36 31
37 import java.util.Map; 32 import java.util.Map;
38 import java.util.Optional; 33 import java.util.Optional;
39 34
40 @Service 35 @Service
41 @TbCoreComponent 36 @TbCoreComponent
  37 +@RequiredArgsConstructor
42 public class AssetBulkImportService extends AbstractBulkImportService<Asset> { 38 public class AssetBulkImportService extends AbstractBulkImportService<Asset> {
43 private final AssetService assetService; 39 private final AssetService assetService;
44 40
45 - public AssetBulkImportService(TelemetrySubscriptionService tsSubscriptionService, TbTenantProfileCache tenantProfileCache,  
46 - AccessControlService accessControlService, AccessValidator accessValidator,  
47 - EntityActionService entityActionService, TbClusterService clusterService, AssetService assetService) {  
48 - super(tsSubscriptionService, tenantProfileCache, accessControlService, accessValidator, entityActionService, clusterService);  
49 - this.assetService = assetService;  
50 - }  
51 -  
52 @Override 41 @Override
53 - protected ImportedEntityInfo<Asset> saveEntity(BulkImportRequest importRequest, Map<BulkImportColumnType, String> fields, SecurityUser user) {  
54 - ImportedEntityInfo<Asset> importedEntityInfo = new ImportedEntityInfo<>();  
55 -  
56 - Asset asset = new Asset();  
57 - asset.setTenantId(user.getTenantId());  
58 - setAssetFields(asset, fields);  
59 -  
60 - Asset existingAsset = assetService.findAssetByTenantIdAndName(user.getTenantId(), asset.getName());  
61 - if (existingAsset != null && importRequest.getMapping().getUpdate()) {  
62 - importedEntityInfo.setOldEntity(new Asset(existingAsset));  
63 - importedEntityInfo.setUpdated(true);  
64 - existingAsset.update(asset);  
65 - asset = existingAsset;  
66 - }  
67 - asset = assetService.saveAsset(asset);  
68 -  
69 - importedEntityInfo.setEntity(asset);  
70 - return importedEntityInfo;  
71 - }  
72 -  
73 - private void setAssetFields(Asset asset, Map<BulkImportColumnType, String> fields) {  
74 - ObjectNode additionalInfo = (ObjectNode) Optional.ofNullable(asset.getAdditionalInfo()).orElseGet(JacksonUtil::newObjectNode); 42 + protected void setEntityFields(Asset entity, Map<BulkImportColumnType, String> fields) {
  43 + ObjectNode additionalInfo = (ObjectNode) Optional.ofNullable(entity.getAdditionalInfo()).orElseGet(JacksonUtil::newObjectNode);
75 fields.forEach((columnType, value) -> { 44 fields.forEach((columnType, value) -> {
76 switch (columnType) { 45 switch (columnType) {
77 case NAME: 46 case NAME:
78 - asset.setName(value); 47 + entity.setName(value);
79 break; 48 break;
80 case TYPE: 49 case TYPE:
81 - asset.setType(value); 50 + entity.setType(value);
82 break; 51 break;
83 case LABEL: 52 case LABEL:
84 - asset.setLabel(value); 53 + entity.setLabel(value);
85 break; 54 break;
86 case DESCRIPTION: 55 case DESCRIPTION:
87 additionalInfo.set("description", new TextNode(value)); 56 additionalInfo.set("description", new TextNode(value));
88 break; 57 break;
89 } 58 }
90 }); 59 });
91 - asset.setAdditionalInfo(additionalInfo); 60 + entity.setAdditionalInfo(additionalInfo);
  61 + }
  62 +
  63 + @Override
  64 + protected Asset saveEntity(Asset entity, Map<BulkImportColumnType, String> fields) {
  65 + return assetService.saveAsset(entity);
  66 + }
  67 +
  68 + @Override
  69 + protected Asset findOrCreateEntity(TenantId tenantId, String name) {
  70 + return Optional.ofNullable(assetService.findAssetByTenantIdAndName(tenantId, name))
  71 + .orElseGet(Asset::new);
  72 + }
  73 +
  74 + @Override
  75 + protected void setOwners(Asset entity, SecurityUser user) {
  76 + entity.setTenantId(user.getTenantId());
  77 + entity.setCustomerId(user.getCustomerId());
  78 + }
  79 +
  80 + @Override
  81 + protected EntityType getEntityType() {
  82 + return EntityType.ASSET;
92 } 83 }
93 84
94 } 85 }
@@ -18,18 +18,19 @@ package org.thingsboard.server.service.device; @@ -18,18 +18,19 @@ package org.thingsboard.server.service.device;
18 import com.fasterxml.jackson.databind.node.BooleanNode; 18 import com.fasterxml.jackson.databind.node.BooleanNode;
19 import com.fasterxml.jackson.databind.node.ObjectNode; 19 import com.fasterxml.jackson.databind.node.ObjectNode;
20 import com.fasterxml.jackson.databind.node.TextNode; 20 import com.fasterxml.jackson.databind.node.TextNode;
  21 +import lombok.RequiredArgsConstructor;
21 import lombok.SneakyThrows; 22 import lombok.SneakyThrows;
22 import org.apache.commons.collections.CollectionUtils; 23 import org.apache.commons.collections.CollectionUtils;
23 import org.apache.commons.lang3.RandomStringUtils; 24 import org.apache.commons.lang3.RandomStringUtils;
24 import org.apache.commons.lang3.StringUtils; 25 import org.apache.commons.lang3.StringUtils;
25 import org.springframework.stereotype.Service; 26 import org.springframework.stereotype.Service;
26 import org.thingsboard.common.util.JacksonUtil; 27 import org.thingsboard.common.util.JacksonUtil;
27 -import org.thingsboard.server.cluster.TbClusterService;  
28 import org.thingsboard.server.common.data.Device; 28 import org.thingsboard.server.common.data.Device;
29 import org.thingsboard.server.common.data.DeviceProfile; 29 import org.thingsboard.server.common.data.DeviceProfile;
30 import org.thingsboard.server.common.data.DeviceProfileProvisionType; 30 import org.thingsboard.server.common.data.DeviceProfileProvisionType;
31 import org.thingsboard.server.common.data.DeviceProfileType; 31 import org.thingsboard.server.common.data.DeviceProfileType;
32 import org.thingsboard.server.common.data.DeviceTransportType; 32 import org.thingsboard.server.common.data.DeviceTransportType;
  33 +import org.thingsboard.server.common.data.EntityType;
33 import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials; 34 import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
34 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials; 35 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials;
35 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode; 36 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
@@ -45,17 +46,10 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService; @@ -45,17 +46,10 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService;
45 import org.thingsboard.server.dao.device.DeviceProfileService; 46 import org.thingsboard.server.dao.device.DeviceProfileService;
46 import org.thingsboard.server.dao.device.DeviceService; 47 import org.thingsboard.server.dao.device.DeviceService;
47 import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException; 48 import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException;
48 -import org.thingsboard.server.dao.tenant.TbTenantProfileCache;  
49 import org.thingsboard.server.queue.util.TbCoreComponent; 49 import org.thingsboard.server.queue.util.TbCoreComponent;
50 -import org.thingsboard.server.service.action.EntityActionService;  
51 import org.thingsboard.server.service.importing.AbstractBulkImportService; 50 import org.thingsboard.server.service.importing.AbstractBulkImportService;
52 import org.thingsboard.server.service.importing.BulkImportColumnType; 51 import org.thingsboard.server.service.importing.BulkImportColumnType;
53 -import org.thingsboard.server.service.importing.BulkImportRequest;  
54 -import org.thingsboard.server.service.importing.ImportedEntityInfo;  
55 -import org.thingsboard.server.service.security.AccessValidator;  
56 import org.thingsboard.server.service.security.model.SecurityUser; 52 import org.thingsboard.server.service.security.model.SecurityUser;
57 -import org.thingsboard.server.service.security.permission.AccessControlService;  
58 -import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;  
59 53
60 import java.util.Collection; 54 import java.util.Collection;
61 import java.util.EnumSet; 55 import java.util.EnumSet;
@@ -68,6 +62,7 @@ import java.util.concurrent.locks.ReentrantLock; @@ -68,6 +62,7 @@ import java.util.concurrent.locks.ReentrantLock;
68 62
69 @Service 63 @Service
70 @TbCoreComponent 64 @TbCoreComponent
  65 +@RequiredArgsConstructor
71 public class DeviceBulkImportService extends AbstractBulkImportService<Device> { 66 public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
72 protected final DeviceService deviceService; 67 protected final DeviceService deviceService;
73 protected final DeviceCredentialsService deviceCredentialsService; 68 protected final DeviceCredentialsService deviceCredentialsService;
@@ -75,33 +70,33 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> { @@ -75,33 +70,33 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
75 70
76 private final Lock findOrCreateDeviceProfileLock = new ReentrantLock(); 71 private final Lock findOrCreateDeviceProfileLock = new ReentrantLock();
77 72
78 - public DeviceBulkImportService(TelemetrySubscriptionService tsSubscriptionService, TbTenantProfileCache tenantProfileCache,  
79 - AccessControlService accessControlService, AccessValidator accessValidator,  
80 - EntityActionService entityActionService, TbClusterService clusterService,  
81 - DeviceService deviceService, DeviceCredentialsService deviceCredentialsService,  
82 - DeviceProfileService deviceProfileService) {  
83 - super(tsSubscriptionService, tenantProfileCache, accessControlService, accessValidator, entityActionService, clusterService);  
84 - this.deviceService = deviceService;  
85 - this.deviceCredentialsService = deviceCredentialsService;  
86 - this.deviceProfileService = deviceProfileService; 73 + @Override
  74 + protected void setEntityFields(Device entity, Map<BulkImportColumnType, String> fields) {
  75 + ObjectNode additionalInfo = (ObjectNode) Optional.ofNullable(entity.getAdditionalInfo()).orElseGet(JacksonUtil::newObjectNode);
  76 + fields.forEach((columnType, value) -> {
  77 + switch (columnType) {
  78 + case NAME:
  79 + entity.setName(value);
  80 + break;
  81 + case TYPE:
  82 + entity.setType(value);
  83 + break;
  84 + case LABEL:
  85 + entity.setLabel(value);
  86 + break;
  87 + case DESCRIPTION:
  88 + additionalInfo.set("description", new TextNode(value));
  89 + break;
  90 + case IS_GATEWAY:
  91 + additionalInfo.set("gateway", BooleanNode.valueOf(Boolean.parseBoolean(value)));
  92 + break;
  93 + }
  94 + entity.setAdditionalInfo(additionalInfo);
  95 + });
87 } 96 }
88 97
89 @Override 98 @Override
90 - protected ImportedEntityInfo<Device> saveEntity(BulkImportRequest importRequest, Map<BulkImportColumnType, String> fields, SecurityUser user) {  
91 - ImportedEntityInfo<Device> importedEntityInfo = new ImportedEntityInfo<>();  
92 -  
93 - Device device = new Device();  
94 - device.setTenantId(user.getTenantId());  
95 - setDeviceFields(device, fields);  
96 -  
97 - Device existingDevice = deviceService.findDeviceByTenantIdAndName(user.getTenantId(), device.getName());  
98 - if (existingDevice != null && importRequest.getMapping().getUpdate()) {  
99 - importedEntityInfo.setOldEntity(new Device(existingDevice));  
100 - importedEntityInfo.setUpdated(true);  
101 - existingDevice.updateDevice(device);  
102 - device = existingDevice;  
103 - }  
104 - 99 + protected Device saveEntity(Device entity, Map<BulkImportColumnType, String> fields) {
105 DeviceCredentials deviceCredentials; 100 DeviceCredentials deviceCredentials;
106 try { 101 try {
107 deviceCredentials = createDeviceCredentials(fields); 102 deviceCredentials = createDeviceCredentials(fields);
@@ -112,42 +107,27 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> { @@ -112,42 +107,27 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
112 107
113 DeviceProfile deviceProfile; 108 DeviceProfile deviceProfile;
114 if (deviceCredentials.getCredentialsType() == DeviceCredentialsType.LWM2M_CREDENTIALS) { 109 if (deviceCredentials.getCredentialsType() == DeviceCredentialsType.LWM2M_CREDENTIALS) {
115 - deviceProfile = setUpLwM2mDeviceProfile(user.getTenantId(), device);  
116 - } else if (StringUtils.isNotEmpty(device.getType())) {  
117 - deviceProfile = deviceProfileService.findOrCreateDeviceProfile(user.getTenantId(), device.getType()); 110 + deviceProfile = setUpLwM2mDeviceProfile(entity.getTenantId(), entity);
  111 + } else if (StringUtils.isNotEmpty(entity.getType())) {
  112 + deviceProfile = deviceProfileService.findOrCreateDeviceProfile(entity.getTenantId(), entity.getType());
118 } else { 113 } else {
119 - deviceProfile = deviceProfileService.findDefaultDeviceProfile(user.getTenantId()); 114 + deviceProfile = deviceProfileService.findDefaultDeviceProfile(entity.getTenantId());
120 } 115 }
121 - device.setDeviceProfileId(deviceProfile.getId()); 116 + entity.setDeviceProfileId(deviceProfile.getId());
122 117
123 - device = deviceService.saveDeviceWithCredentials(device, deviceCredentials); 118 + return deviceService.saveDeviceWithCredentials(entity, deviceCredentials);
  119 + }
124 120
125 - importedEntityInfo.setEntity(device);  
126 - return importedEntityInfo; 121 + @Override
  122 + protected Device findOrCreateEntity(TenantId tenantId, String name) {
  123 + return Optional.ofNullable(deviceService.findDeviceByTenantIdAndName(tenantId, name))
  124 + .orElseGet(Device::new);
127 } 125 }
128 126
129 - private void setDeviceFields(Device device, Map<BulkImportColumnType, String> fields) {  
130 - ObjectNode additionalInfo = (ObjectNode) Optional.ofNullable(device.getAdditionalInfo()).orElseGet(JacksonUtil::newObjectNode);  
131 - fields.forEach((columnType, value) -> {  
132 - switch (columnType) {  
133 - case NAME:  
134 - device.setName(value);  
135 - break;  
136 - case TYPE:  
137 - device.setType(value);  
138 - break;  
139 - case LABEL:  
140 - device.setLabel(value);  
141 - break;  
142 - case DESCRIPTION:  
143 - additionalInfo.set("description", new TextNode(value));  
144 - break;  
145 - case IS_GATEWAY:  
146 - additionalInfo.set("gateway", BooleanNode.valueOf(Boolean.parseBoolean(value)));  
147 - break;  
148 - }  
149 - device.setAdditionalInfo(additionalInfo);  
150 - }); 127 + @Override
  128 + protected void setOwners(Device entity, SecurityUser user) {
  129 + entity.setTenantId(user.getTenantId());
  130 + entity.setCustomerId(user.getCustomerId());
151 } 131 }
152 132
153 @SneakyThrows 133 @SneakyThrows
@@ -273,4 +253,9 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> { @@ -273,4 +253,9 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
273 } 253 }
274 } 254 }
275 255
  256 + @Override
  257 + protected EntityType getEntityType() {
  258 + return EntityType.DEVICE;
  259 + }
  260 +
276 } 261 }
@@ -17,90 +17,81 @@ package org.thingsboard.server.service.edge; @@ -17,90 +17,81 @@ package org.thingsboard.server.service.edge;
17 17
18 import com.fasterxml.jackson.databind.node.ObjectNode; 18 import com.fasterxml.jackson.databind.node.ObjectNode;
19 import com.fasterxml.jackson.databind.node.TextNode; 19 import com.fasterxml.jackson.databind.node.TextNode;
  20 +import lombok.RequiredArgsConstructor;
20 import org.springframework.stereotype.Service; 21 import org.springframework.stereotype.Service;
21 import org.thingsboard.common.util.JacksonUtil; 22 import org.thingsboard.common.util.JacksonUtil;
22 -import org.thingsboard.server.cluster.TbClusterService; 23 +import org.thingsboard.server.common.data.EntityType;
23 import org.thingsboard.server.common.data.edge.Edge; 24 import org.thingsboard.server.common.data.edge.Edge;
  25 +import org.thingsboard.server.common.data.id.TenantId;
24 import org.thingsboard.server.dao.edge.EdgeService; 26 import org.thingsboard.server.dao.edge.EdgeService;
25 -import org.thingsboard.server.dao.tenant.TbTenantProfileCache;  
26 import org.thingsboard.server.queue.util.TbCoreComponent; 27 import org.thingsboard.server.queue.util.TbCoreComponent;
27 -import org.thingsboard.server.service.action.EntityActionService;  
28 import org.thingsboard.server.service.importing.AbstractBulkImportService; 28 import org.thingsboard.server.service.importing.AbstractBulkImportService;
29 import org.thingsboard.server.service.importing.BulkImportColumnType; 29 import org.thingsboard.server.service.importing.BulkImportColumnType;
30 -import org.thingsboard.server.service.importing.BulkImportRequest;  
31 -import org.thingsboard.server.service.importing.ImportedEntityInfo;  
32 -import org.thingsboard.server.service.security.AccessValidator;  
33 import org.thingsboard.server.service.security.model.SecurityUser; 30 import org.thingsboard.server.service.security.model.SecurityUser;
34 -import org.thingsboard.server.service.security.permission.AccessControlService;  
35 -import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;  
36 31
37 import java.util.Map; 32 import java.util.Map;
38 import java.util.Optional; 33 import java.util.Optional;
39 34
40 @Service 35 @Service
41 @TbCoreComponent 36 @TbCoreComponent
  37 +@RequiredArgsConstructor
42 public class EdgeBulkImportService extends AbstractBulkImportService<Edge> { 38 public class EdgeBulkImportService extends AbstractBulkImportService<Edge> {
43 private final EdgeService edgeService; 39 private final EdgeService edgeService;
44 40
45 - public EdgeBulkImportService(TelemetrySubscriptionService tsSubscriptionService, TbTenantProfileCache tenantProfileCache,  
46 - AccessControlService accessControlService, AccessValidator accessValidator,  
47 - EntityActionService entityActionService, TbClusterService clusterService, EdgeService edgeService) {  
48 - super(tsSubscriptionService, tenantProfileCache, accessControlService, accessValidator, entityActionService, clusterService);  
49 - this.edgeService = edgeService;  
50 - }  
51 -  
52 @Override 41 @Override
53 - protected ImportedEntityInfo<Edge> saveEntity(BulkImportRequest importRequest, Map<BulkImportColumnType, String> fields, SecurityUser user) {  
54 - ImportedEntityInfo<Edge> importedEntityInfo = new ImportedEntityInfo<>();  
55 -  
56 - Edge edge = new Edge();  
57 - edge.setTenantId(user.getTenantId());  
58 - setEdgeFields(edge, fields);  
59 -  
60 - Edge existingEdge = edgeService.findEdgeByTenantIdAndName(user.getTenantId(), edge.getName());  
61 - if (existingEdge != null && importRequest.getMapping().getUpdate()) {  
62 - importedEntityInfo.setOldEntity(new Edge(existingEdge));  
63 - importedEntityInfo.setUpdated(true);  
64 - existingEdge.update(edge);  
65 - edge = existingEdge;  
66 - }  
67 - edge = edgeService.saveEdge(edge, true);  
68 -  
69 - importedEntityInfo.setEntity(edge);  
70 - return importedEntityInfo;  
71 - }  
72 -  
73 - private void setEdgeFields(Edge edge, Map<BulkImportColumnType, String> fields) {  
74 - ObjectNode additionalInfo = (ObjectNode) Optional.ofNullable(edge.getAdditionalInfo()).orElseGet(JacksonUtil::newObjectNode); 42 + protected void setEntityFields(Edge entity, Map<BulkImportColumnType, String> fields) {
  43 + ObjectNode additionalInfo = (ObjectNode) Optional.ofNullable(entity.getAdditionalInfo()).orElseGet(JacksonUtil::newObjectNode);
75 fields.forEach((columnType, value) -> { 44 fields.forEach((columnType, value) -> {
76 switch (columnType) { 45 switch (columnType) {
77 case NAME: 46 case NAME:
78 - edge.setName(value); 47 + entity.setName(value);
79 break; 48 break;
80 case TYPE: 49 case TYPE:
81 - edge.setType(value); 50 + entity.setType(value);
82 break; 51 break;
83 case LABEL: 52 case LABEL:
84 - edge.setLabel(value); 53 + entity.setLabel(value);
85 break; 54 break;
86 case DESCRIPTION: 55 case DESCRIPTION:
87 additionalInfo.set("description", new TextNode(value)); 56 additionalInfo.set("description", new TextNode(value));
88 break; 57 break;
89 case EDGE_LICENSE_KEY: 58 case EDGE_LICENSE_KEY:
90 - edge.setEdgeLicenseKey(value); 59 + entity.setEdgeLicenseKey(value);
91 break; 60 break;
92 case CLOUD_ENDPOINT: 61 case CLOUD_ENDPOINT:
93 - edge.setCloudEndpoint(value); 62 + entity.setCloudEndpoint(value);
94 break; 63 break;
95 case ROUTING_KEY: 64 case ROUTING_KEY:
96 - edge.setRoutingKey(value); 65 + entity.setRoutingKey(value);
97 break; 66 break;
98 case SECRET: 67 case SECRET:
99 - edge.setSecret(value); 68 + entity.setSecret(value);
100 break; 69 break;
101 } 70 }
102 }); 71 });
103 - edge.setAdditionalInfo(additionalInfo); 72 + entity.setAdditionalInfo(additionalInfo);
  73 + }
  74 +
  75 + @Override
  76 + protected Edge saveEntity(Edge entity, Map<BulkImportColumnType, String> fields) {
  77 + return edgeService.saveEdge(entity, true);
  78 + }
  79 +
  80 + @Override
  81 + protected Edge findOrCreateEntity(TenantId tenantId, String name) {
  82 + return Optional.ofNullable(edgeService.findEdgeByTenantIdAndName(tenantId, name))
  83 + .orElseGet(Edge::new);
  84 + }
  85 +
  86 + @Override
  87 + protected void setOwners(Edge entity, SecurityUser user) {
  88 + entity.setTenantId(user.getTenantId());
  89 + entity.setCustomerId(user.getCustomerId());
  90 + }
  91 +
  92 + @Override
  93 + protected EntityType getEntityType() {
  94 + return EntityType.EDGE;
104 } 95 }
105 96
106 } 97 }
@@ -19,19 +19,21 @@ import com.google.common.util.concurrent.FutureCallback; @@ -19,19 +19,21 @@ import com.google.common.util.concurrent.FutureCallback;
19 import com.google.gson.JsonObject; 19 import com.google.gson.JsonObject;
20 import com.google.gson.JsonPrimitive; 20 import com.google.gson.JsonPrimitive;
21 import lombok.Data; 21 import lombok.Data;
22 -import lombok.RequiredArgsConstructor;  
23 import lombok.SneakyThrows; 22 import lombok.SneakyThrows;
24 import org.apache.commons.lang3.StringUtils; 23 import org.apache.commons.lang3.StringUtils;
25 import org.apache.commons.lang3.exception.ExceptionUtils; 24 import org.apache.commons.lang3.exception.ExceptionUtils;
  25 +import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.security.core.context.SecurityContext; 26 import org.springframework.security.core.context.SecurityContext;
27 import org.springframework.security.core.context.SecurityContextHolder; 27 import org.springframework.security.core.context.SecurityContextHolder;
28 import org.thingsboard.common.util.DonAsynchron; 28 import org.thingsboard.common.util.DonAsynchron;
29 import org.thingsboard.common.util.ThingsBoardThreadFactory; 29 import org.thingsboard.common.util.ThingsBoardThreadFactory;
30 -import org.thingsboard.server.cluster.TbClusterService;  
31 -import org.thingsboard.server.common.data.BaseData; 30 +import org.thingsboard.server.common.data.EntityType;
  31 +import org.thingsboard.server.common.data.HasTenantId;
32 import org.thingsboard.server.common.data.TenantProfile; 32 import org.thingsboard.server.common.data.TenantProfile;
33 import org.thingsboard.server.common.data.audit.ActionType; 33 import org.thingsboard.server.common.data.audit.ActionType;
34 import org.thingsboard.server.common.data.id.EntityId; 34 import org.thingsboard.server.common.data.id.EntityId;
  35 +import org.thingsboard.server.common.data.id.HasId;
  36 +import org.thingsboard.server.common.data.id.TenantId;
35 import org.thingsboard.server.common.data.id.UUIDBased; 37 import org.thingsboard.server.common.data.id.UUIDBased;
36 import org.thingsboard.server.common.data.kv.AttributeKvEntry; 38 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
37 import org.thingsboard.server.common.data.kv.BasicTsKvEntry; 39 import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
@@ -47,6 +49,7 @@ import org.thingsboard.server.service.security.AccessValidator; @@ -47,6 +49,7 @@ import org.thingsboard.server.service.security.AccessValidator;
47 import org.thingsboard.server.service.security.model.SecurityUser; 49 import org.thingsboard.server.service.security.model.SecurityUser;
48 import org.thingsboard.server.service.security.permission.AccessControlService; 50 import org.thingsboard.server.service.security.permission.AccessControlService;
49 import org.thingsboard.server.service.security.permission.Operation; 51 import org.thingsboard.server.service.security.permission.Operation;
  52 +import org.thingsboard.server.service.security.permission.Resource;
50 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService; 53 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
51 import org.thingsboard.server.utils.CsvUtils; 54 import org.thingsboard.server.utils.CsvUtils;
52 import org.thingsboard.server.utils.TypeCastUtil; 55 import org.thingsboard.server.utils.TypeCastUtil;
@@ -68,14 +71,17 @@ import java.util.function.Consumer; @@ -68,14 +71,17 @@ import java.util.function.Consumer;
68 import java.util.stream.Collectors; 71 import java.util.stream.Collectors;
69 import java.util.stream.Stream; 72 import java.util.stream.Stream;
70 73
71 -@RequiredArgsConstructor  
72 -public abstract class AbstractBulkImportService<E extends BaseData<? extends EntityId>> {  
73 - protected final TelemetrySubscriptionService tsSubscriptionService;  
74 - protected final TbTenantProfileCache tenantProfileCache;  
75 - protected final AccessControlService accessControlService;  
76 - protected final AccessValidator accessValidator;  
77 - protected final EntityActionService entityActionService;  
78 - protected final TbClusterService clusterService; 74 +public abstract class AbstractBulkImportService<E extends HasId<? extends EntityId> & HasTenantId> {
  75 + @Autowired
  76 + private TelemetrySubscriptionService tsSubscriptionService;
  77 + @Autowired
  78 + private TbTenantProfileCache tenantProfileCache;
  79 + @Autowired
  80 + private AccessControlService accessControlService;
  81 + @Autowired
  82 + private AccessValidator accessValidator;
  83 + @Autowired
  84 + private EntityActionService entityActionService;
79 85
80 private static ThreadPoolExecutor executor; 86 private static ThreadPoolExecutor executor;
81 87
@@ -100,7 +106,7 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent @@ -100,7 +106,7 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent
100 entitiesData.forEach(entityData -> DonAsynchron.submit(() -> { 106 entitiesData.forEach(entityData -> DonAsynchron.submit(() -> {
101 SecurityContextHolder.setContext(securityContext); 107 SecurityContextHolder.setContext(securityContext);
102 108
103 - ImportedEntityInfo<E> importedEntityInfo = saveEntity(request, entityData.getFields(), user); 109 + ImportedEntityInfo<E> importedEntityInfo = saveEntity(entityData.getFields(), user);
104 E entity = importedEntityInfo.getEntity(); 110 E entity = importedEntityInfo.getEntity();
105 111
106 onEntityImported.accept(importedEntityInfo); 112 onEntityImported.accept(importedEntityInfo);
@@ -127,12 +133,39 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent @@ -127,12 +133,39 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent
127 return result; 133 return result;
128 } 134 }
129 135
130 - protected abstract ImportedEntityInfo<E> saveEntity(BulkImportRequest importRequest, Map<BulkImportColumnType, String> fields, SecurityUser user); 136 + @SneakyThrows
  137 + private ImportedEntityInfo<E> saveEntity(Map<BulkImportColumnType, String> fields, SecurityUser user) {
  138 + ImportedEntityInfo<E> importedEntityInfo = new ImportedEntityInfo<>();
  139 +
  140 + E entity = findOrCreateEntity(user.getTenantId(), fields.get(BulkImportColumnType.NAME));
  141 + if (entity.getId() != null) {
  142 + importedEntityInfo.setOldEntity((E) entity.getClass().getConstructor(entity.getClass()).newInstance(entity));
  143 + importedEntityInfo.setUpdated(true);
  144 + } else {
  145 + setOwners(entity, user);
  146 + }
  147 +
  148 + setEntityFields(entity, fields);
  149 + accessControlService.checkPermission(user, Resource.of(getEntityType()), Operation.WRITE, entity.getId(), entity);
  150 +
  151 + E savedEntity = saveEntity(entity, fields);
  152 +
  153 + importedEntityInfo.setEntity(savedEntity);
  154 + return importedEntityInfo;
  155 + }
  156 +
  157 +
  158 + protected abstract E findOrCreateEntity(TenantId tenantId, String name);
  159 +
  160 + protected abstract void setOwners(E entity, SecurityUser user);
  161 +
  162 + protected abstract void setEntityFields(E entity, Map<BulkImportColumnType, String> fields);
  163 +
  164 + protected abstract E saveEntity(E entity, Map<BulkImportColumnType, String> fields);
  165 +
  166 + protected abstract EntityType getEntityType();
  167 +
131 168
132 - /*  
133 - * Attributes' values are firstly added to JsonObject in order to then make some type cast,  
134 - * because we get all values as strings from CSV  
135 - * */  
136 private void saveKvs(SecurityUser user, E entity, Map<ColumnMapping, ParsedValue> data) { 169 private void saveKvs(SecurityUser user, E entity, Map<ColumnMapping, ParsedValue> data) {
137 Arrays.stream(BulkImportColumnType.values()) 170 Arrays.stream(BulkImportColumnType.values())
138 .filter(BulkImportColumnType::isKv) 171 .filter(BulkImportColumnType::isKv)
@@ -58,7 +58,7 @@ public enum Resource { @@ -58,7 +58,7 @@ public enum Resource {
58 58
59 public static Resource of(EntityType entityType) { 59 public static Resource of(EntityType entityType) {
60 for (Resource resource : Resource.values()) { 60 for (Resource resource : Resource.values()) {
61 - if (resource.getEntityType().get() == entityType) { 61 + if (resource.getEntityType().orElse(null) == entityType) {
62 return resource; 62 return resource;
63 } 63 }
64 } 64 }