Commit 9aecb1463a540e70f72dca2d6197ffd567ff20b7

Authored by Andrii Shvaika
2 parents 423c17ab f747c828

Merge branch 'fix/bulk-import' of https://github.com/ViacheslavKlimov/thingsboard

... ... @@ -17,78 +17,69 @@ package org.thingsboard.server.service.asset;
17 17
18 18 import com.fasterxml.jackson.databind.node.ObjectNode;
19 19 import com.fasterxml.jackson.databind.node.TextNode;
  20 +import lombok.RequiredArgsConstructor;
20 21 import org.springframework.stereotype.Service;
21 22 import org.thingsboard.common.util.JacksonUtil;
22   -import org.thingsboard.server.cluster.TbClusterService;
  23 +import org.thingsboard.server.common.data.EntityType;
23 24 import org.thingsboard.server.common.data.asset.Asset;
  25 +import org.thingsboard.server.common.data.id.TenantId;
24 26 import org.thingsboard.server.dao.asset.AssetService;
25   -import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
26 27 import org.thingsboard.server.queue.util.TbCoreComponent;
27   -import org.thingsboard.server.service.action.EntityActionService;
28 28 import org.thingsboard.server.service.importing.AbstractBulkImportService;
29 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 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 32 import java.util.Map;
38 33 import java.util.Optional;
39 34
40 35 @Service
41 36 @TbCoreComponent
  37 +@RequiredArgsConstructor
42 38 public class AssetBulkImportService extends AbstractBulkImportService<Asset> {
43 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 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 44 fields.forEach((columnType, value) -> {
76 45 switch (columnType) {
77 46 case NAME:
78   - asset.setName(value);
  47 + entity.setName(value);
79 48 break;
80 49 case TYPE:
81   - asset.setType(value);
  50 + entity.setType(value);
82 51 break;
83 52 case LABEL:
84   - asset.setLabel(value);
  53 + entity.setLabel(value);
85 54 break;
86 55 case DESCRIPTION:
87 56 additionalInfo.set("description", new TextNode(value));
88 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 import com.fasterxml.jackson.databind.node.BooleanNode;
19 19 import com.fasterxml.jackson.databind.node.ObjectNode;
20 20 import com.fasterxml.jackson.databind.node.TextNode;
  21 +import lombok.RequiredArgsConstructor;
21 22 import lombok.SneakyThrows;
22 23 import org.apache.commons.collections.CollectionUtils;
23 24 import org.apache.commons.lang3.RandomStringUtils;
24 25 import org.apache.commons.lang3.StringUtils;
25 26 import org.springframework.stereotype.Service;
26 27 import org.thingsboard.common.util.JacksonUtil;
27   -import org.thingsboard.server.cluster.TbClusterService;
28 28 import org.thingsboard.server.common.data.Device;
29 29 import org.thingsboard.server.common.data.DeviceProfile;
30 30 import org.thingsboard.server.common.data.DeviceProfileProvisionType;
31 31 import org.thingsboard.server.common.data.DeviceProfileType;
32 32 import org.thingsboard.server.common.data.DeviceTransportType;
  33 +import org.thingsboard.server.common.data.EntityType;
33 34 import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
34 35 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MClientCredentials;
35 36 import org.thingsboard.server.common.data.device.credentials.lwm2m.LwM2MSecurityMode;
... ... @@ -45,17 +46,10 @@ import org.thingsboard.server.dao.device.DeviceCredentialsService;
45 46 import org.thingsboard.server.dao.device.DeviceProfileService;
46 47 import org.thingsboard.server.dao.device.DeviceService;
47 48 import org.thingsboard.server.dao.exception.DeviceCredentialsValidationException;
48   -import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
49 49 import org.thingsboard.server.queue.util.TbCoreComponent;
50   -import org.thingsboard.server.service.action.EntityActionService;
51 50 import org.thingsboard.server.service.importing.AbstractBulkImportService;
52 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 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 54 import java.util.Collection;
61 55 import java.util.EnumSet;
... ... @@ -68,6 +62,7 @@ import java.util.concurrent.locks.ReentrantLock;
68 62
69 63 @Service
70 64 @TbCoreComponent
  65 +@RequiredArgsConstructor
71 66 public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
72 67 protected final DeviceService deviceService;
73 68 protected final DeviceCredentialsService deviceCredentialsService;
... ... @@ -75,33 +70,33 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
75 70
76 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 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 100 DeviceCredentials deviceCredentials;
106 101 try {
107 102 deviceCredentials = createDeviceCredentials(fields);
... ... @@ -112,42 +107,27 @@ public class DeviceBulkImportService extends AbstractBulkImportService<Device> {
112 107
113 108 DeviceProfile deviceProfile;
114 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 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 133 @SneakyThrows
... ... @@ -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 17
18 18 import com.fasterxml.jackson.databind.node.ObjectNode;
19 19 import com.fasterxml.jackson.databind.node.TextNode;
  20 +import lombok.RequiredArgsConstructor;
20 21 import org.springframework.stereotype.Service;
21 22 import org.thingsboard.common.util.JacksonUtil;
22   -import org.thingsboard.server.cluster.TbClusterService;
  23 +import org.thingsboard.server.common.data.EntityType;
23 24 import org.thingsboard.server.common.data.edge.Edge;
  25 +import org.thingsboard.server.common.data.id.TenantId;
24 26 import org.thingsboard.server.dao.edge.EdgeService;
25   -import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
26 27 import org.thingsboard.server.queue.util.TbCoreComponent;
27   -import org.thingsboard.server.service.action.EntityActionService;
28 28 import org.thingsboard.server.service.importing.AbstractBulkImportService;
29 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 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 32 import java.util.Map;
38 33 import java.util.Optional;
39 34
40 35 @Service
41 36 @TbCoreComponent
  37 +@RequiredArgsConstructor
42 38 public class EdgeBulkImportService extends AbstractBulkImportService<Edge> {
43 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 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 44 fields.forEach((columnType, value) -> {
76 45 switch (columnType) {
77 46 case NAME:
78   - edge.setName(value);
  47 + entity.setName(value);
79 48 break;
80 49 case TYPE:
81   - edge.setType(value);
  50 + entity.setType(value);
82 51 break;
83 52 case LABEL:
84   - edge.setLabel(value);
  53 + entity.setLabel(value);
85 54 break;
86 55 case DESCRIPTION:
87 56 additionalInfo.set("description", new TextNode(value));
88 57 break;
89 58 case EDGE_LICENSE_KEY:
90   - edge.setEdgeLicenseKey(value);
  59 + entity.setEdgeLicenseKey(value);
91 60 break;
92 61 case CLOUD_ENDPOINT:
93   - edge.setCloudEndpoint(value);
  62 + entity.setCloudEndpoint(value);
94 63 break;
95 64 case ROUTING_KEY:
96   - edge.setRoutingKey(value);
  65 + entity.setRoutingKey(value);
97 66 break;
98 67 case SECRET:
99   - edge.setSecret(value);
  68 + entity.setSecret(value);
100 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 import com.google.gson.JsonObject;
20 20 import com.google.gson.JsonPrimitive;
21 21 import lombok.Data;
22   -import lombok.RequiredArgsConstructor;
23 22 import lombok.SneakyThrows;
24 23 import org.apache.commons.lang3.StringUtils;
25 24 import org.apache.commons.lang3.exception.ExceptionUtils;
  25 +import org.springframework.beans.factory.annotation.Autowired;
26 26 import org.springframework.security.core.context.SecurityContext;
27 27 import org.springframework.security.core.context.SecurityContextHolder;
28 28 import org.thingsboard.common.util.DonAsynchron;
29 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 32 import org.thingsboard.server.common.data.TenantProfile;
33 33 import org.thingsboard.server.common.data.audit.ActionType;
34 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 37 import org.thingsboard.server.common.data.id.UUIDBased;
36 38 import org.thingsboard.server.common.data.kv.AttributeKvEntry;
37 39 import org.thingsboard.server.common.data.kv.BasicTsKvEntry;
... ... @@ -47,6 +49,7 @@ import org.thingsboard.server.service.security.AccessValidator;
47 49 import org.thingsboard.server.service.security.model.SecurityUser;
48 50 import org.thingsboard.server.service.security.permission.AccessControlService;
49 51 import org.thingsboard.server.service.security.permission.Operation;
  52 +import org.thingsboard.server.service.security.permission.Resource;
50 53 import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
51 54 import org.thingsboard.server.utils.CsvUtils;
52 55 import org.thingsboard.server.utils.TypeCastUtil;
... ... @@ -68,14 +71,17 @@ import java.util.function.Consumer;
68 71 import java.util.stream.Collectors;
69 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 86 private static ThreadPoolExecutor executor;
81 87
... ... @@ -100,7 +106,7 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent
100 106 entitiesData.forEach(entityData -> DonAsynchron.submit(() -> {
101 107 SecurityContextHolder.setContext(securityContext);
102 108
103   - ImportedEntityInfo<E> importedEntityInfo = saveEntity(request, entityData.getFields(), user);
  109 + ImportedEntityInfo<E> importedEntityInfo = saveEntity(entityData.getFields(), user);
104 110 E entity = importedEntityInfo.getEntity();
105 111
106 112 onEntityImported.accept(importedEntityInfo);
... ... @@ -127,12 +133,39 @@ public abstract class AbstractBulkImportService<E extends BaseData<? extends Ent
127 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 169 private void saveKvs(SecurityUser user, E entity, Map<ColumnMapping, ParsedValue> data) {
137 170 Arrays.stream(BulkImportColumnType.values())
138 171 .filter(BulkImportColumnType::isKv)
... ...
... ... @@ -58,7 +58,7 @@ public enum Resource {
58 58
59 59 public static Resource of(EntityType entityType) {
60 60 for (Resource resource : Resource.values()) {
61   - if (resource.getEntityType().get() == entityType) {
  61 + if (resource.getEntityType().orElse(null) == entityType) {
62 62 return resource;
63 63 }
64 64 }
... ...