diff --git a/application/src/main/java/org/thingsboard/server/controller/EntitiesExportImportController.java b/application/src/main/java/org/thingsboard/server/controller/EntitiesExportImportController.java index a3f26bf7b0..96bc70656f 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntitiesExportImportController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntitiesExportImportController.java @@ -17,11 +17,13 @@ package org.thingsboard.server.controller; import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; +import org.apache.commons.collections.CollectionUtils; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.exception.ThingsboardException; @@ -29,14 +31,18 @@ import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.ExportableEntity; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityIdFactory; +import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.expimp.EntitiesExportImportService; +import org.thingsboard.server.service.expimp.exp.EntityExportSettings; import org.thingsboard.server.service.expimp.imp.EntityImportResult; +import org.thingsboard.server.service.expimp.imp.EntityImportSettings; import org.thingsboard.server.service.security.model.SecurityUser; import org.thingsboard.server.service.security.permission.Operation; import org.thingsboard.server.service.security.permission.Resource; import java.util.UUID; +import java.util.stream.Collectors; @RestController @RequestMapping("/api/entities") @@ -49,66 +55,60 @@ public class EntitiesExportImportController extends BaseController { @PostMapping("/export/{entityType}/{entityId}") @PreAuthorize("hasAuthority('TENANT_ADMIN')") - public EntityExportData exportEntity(@ApiParam(allowableValues = "DEVICE, DEVICE_PROFILE, ASSET, RULE_CHAIN, DASHBOARD, CUSTOMER") @PathVariable EntityType entityType, - @PathVariable("entityId") UUID entityUuid) throws ThingsboardException { + public EntityExportData exportEntity(@ApiParam(allowableValues = "DEVICE, DEVICE_PROFILE, ASSET, RULE_CHAIN, DASHBOARD, CUSTOMER") + @PathVariable EntityType entityType, + @PathVariable("entityId") UUID entityUuid, + @RequestParam(defaultValue = "false") boolean exportInboundRelations) throws ThingsboardException { EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, entityUuid); + EntityExportSettings exportSettings = EntityExportSettings.builder() + .exportInboundRelations(exportInboundRelations) + .build(); try { - return exportEntity(getCurrentUser(), entityId); + return exportEntity(getCurrentUser(), entityId, exportSettings); } catch (Exception e) { throw handleException(e); } } -// @PostMapping("/export/batch") -// @PreAuthorize("hasAuthority('TENANT_ADMIN')") -// public EntitiesExportResponse exportEntities(@RequestBody EntitiesExportRequest exportRequest) throws ThingsboardException { -// TenantId tenantId = getTenantId(); -// -// EntitiesExportResponse exportResponse = new EntitiesExportResponse(); -// -// Map>>> result = new HashMap<>(); -// exportRequest.getEntities().forEach((entityType, entityIds) -> { -// List>> exportDataForEntityType = new LinkedList<>(); -// entityIds.forEach(entityId -> { -// EntityExportData> exportData = exportImportService.exportEntity(tenantId, entityId); -// exportDataForEntityType.add(exportData); -// }); -// result.put(entityType, exportDataForEntityType); -// }); -// -// exportResponse.setExportData(result); -// return exportResponse; -// } - // TODO: export and import of batches - // TODO: api to export and import whole customer, whole tenant - - @PostMapping("/import") @PreAuthorize("hasAuthority('TENANT_ADMIN')") - public EntityImportResult> importEntity(@RequestBody EntityExportData> exportData) throws ThingsboardException { + public EntityImportResult> importEntity(@RequestBody EntityExportData> exportData, + @RequestParam(defaultValue = "false") boolean importInboundRelations) throws ThingsboardException { + EntityImportSettings importSettings = EntityImportSettings.builder() + .importInboundRelations(importInboundRelations) + .build(); try { - return importEntity(getCurrentUser(), exportData); + return importEntity(getCurrentUser(), exportData, importSettings); } catch (Exception e) { throw handleException(e); } } - private EntityExportData> exportEntity(SecurityUser user, EntityId entityId) throws ThingsboardException { + // TODO [viacheslav]: export and import of batches + // TODO [viacheslav]: api to export and import whole customer, whole tenant + + private EntityExportData> exportEntity(SecurityUser user, EntityId entityId, EntityExportSettings exportSettings) throws ThingsboardException { checkEntityId(entityId, Operation.READ); - return exportImportService.exportEntity(getTenantId(), entityId); + return exportImportService.exportEntity(user.getTenantId(), entityId, exportSettings); } - private EntityImportResult> importEntity(SecurityUser user, EntityExportData> exportData) throws ThingsboardException { + private EntityImportResult> importEntity(SecurityUser user, EntityExportData> exportData, EntityImportSettings importSettings) throws ThingsboardException { ExportableEntity existingEntity = exportImportService.findEntityByExternalId(user.getTenantId(), exportData.getMainEntity().getId()); - if (existingEntity != null) { - checkEntityId(existingEntity.getId(), Operation.WRITE); // todo maybe need to extract permission check to BaseController and put there permission checks from other controllers + if (existingEntity != null) {// todo [viacheslav] maybe need to extract permission check to BaseController and put there permission checks from other controllers + checkEntityId(existingEntity.getId(), Operation.WRITE); + if (importSettings.isImportInboundRelations() && CollectionUtils.isNotEmpty(exportData.getInboundRelations())) { + for (EntityId fromId : exportData.getInboundRelations().stream().map(EntityRelation::getFrom).collect(Collectors.toSet())) { + // FIXME [viacheslav]: fromId is external +// checkEntityId(fromId, Operation.WRITE); + } + } } else { checkEntity(null, exportData.getMainEntity(), Resource.of(exportData.getEntityType())); } - EntityImportResult> importResult = exportImportService.importEntity(getTenantId(), exportData); + EntityImportResult> importResult = exportImportService.importEntity(getTenantId(), exportData, importSettings); onEntityUpdatedOrCreated(user, importResult.getSavedEntity(), importResult.getOldEntity(), importResult.getOldEntity() == null); return importResult; diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/DefaultEntitiesExportImportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/DefaultEntitiesExportImportService.java index c6fe03a750..0136bd1d52 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/DefaultEntitiesExportImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/DefaultEntitiesExportImportService.java @@ -25,56 +25,63 @@ import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.ExportableEntityDao; import org.thingsboard.server.queue.util.TbCoreComponent; import org.thingsboard.server.service.expimp.exp.EntityExportService; +import org.thingsboard.server.service.expimp.exp.EntityExportSettings; import org.thingsboard.server.service.expimp.imp.EntityImportResult; import org.thingsboard.server.service.expimp.imp.EntityImportService; +import org.thingsboard.server.service.expimp.imp.EntityImportSettings; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Optional; -// FIXME: review packages and classes naming +// FIXME [viacheslav]: review packages and classes naming @Service @TbCoreComponent public class DefaultEntitiesExportImportService implements EntitiesExportImportService { - private final Map> exportServices = new HashMap<>(); + private final Map> exportServices = new HashMap<>(); private final Map> importServices = new HashMap<>(); private final Map> daos = new HashMap<>(); - // TODO: export and import of the whole tenant - // TODO: export and import of the whole customer ? - // TODO: relations export and import + // TODO [viacheslav]: export and import of the whole tenant + // TODO [viacheslav]: export and import of the whole customer ? @Override - public , I extends EntityId> EntityExportData exportEntity(TenantId tenantId, I entityId) { + public , I extends EntityId> EntityExportData exportEntity(TenantId tenantId, I entityId, EntityExportSettings exportSettings) { EntityType entityType = entityId.getEntityType(); - EntityExportService exportService = getExportService(entityType); + EntityExportService> exportService = getExportService(entityType); - return exportService.getExportData(tenantId, entityId); + return exportService.getExportData(tenantId, entityId, exportSettings); } - // FIXME: somehow validate export data + // FIXME [viacheslav]: somehow validate export data @Override - public , I extends EntityId> EntityImportResult importEntity(TenantId tenantId, EntityExportData exportData) { + public , I extends EntityId> EntityImportResult importEntity(TenantId tenantId, EntityExportData exportData, EntityImportSettings importSettings) { EntityType entityType = exportData.getEntityType(); EntityImportService> importService = getImportService(entityType); - return importService.importEntity(tenantId, exportData); + return importService.importEntity(tenantId, exportData, importSettings); } + @Override + public , I extends EntityId> E findEntityById(TenantId tenantId, I id) { + ExportableEntityDao dao = getDao(id.getEntityType()); + return dao.findByTenantIdAndId(tenantId.getId(), id.getId()); + } + @Override public , I extends EntityId> E findEntityByExternalId(TenantId tenantId, I externalId) { ExportableEntityDao dao = getDao(externalId.getEntityType()); return Optional.ofNullable(dao.findByTenantIdAndExternalId(tenantId.getId(), externalId.getId())) - .orElseGet(() -> dao.findByTenantIdAndId(tenantId.getId(), externalId.getId())); + .orElseGet(() -> findEntityById(tenantId, externalId)); } @SuppressWarnings("unchecked") - private > EntityExportService getExportService(EntityType entityType) { - return (EntityExportService) exportServices.get(entityType); + private , D extends EntityExportData> EntityExportService getExportService(EntityType entityType) { + return (EntityExportService) exportServices.get(entityType); } @SuppressWarnings("unchecked") @@ -88,7 +95,7 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS } @Autowired - private void setServices(Collection> exportServices, + private void setServices(Collection> exportServices, Collection> importServices, Collection> daos) { exportServices.forEach(entityExportService -> { diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/EntitiesExportImportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/EntitiesExportImportService.java index 10361865a2..752d4b6315 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/EntitiesExportImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/EntitiesExportImportService.java @@ -19,12 +19,14 @@ import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.ExportableEntity; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.service.expimp.exp.EntityExportSettings; import org.thingsboard.server.service.expimp.imp.EntityImportResult; +import org.thingsboard.server.service.expimp.imp.EntityImportSettings; public interface EntitiesExportImportService extends ExportableEntitiesService { - , I extends EntityId> EntityExportData exportEntity(TenantId tenantId, I entityId); + , I extends EntityId> EntityExportData exportEntity(TenantId tenantId, I entityId, EntityExportSettings exportSettings); - , I extends EntityId> EntityImportResult importEntity(TenantId tenantId, EntityExportData exportData); + , I extends EntityId> EntityImportResult importEntity(TenantId tenantId, EntityExportData exportData, EntityImportSettings importSettings); } diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/ExportableEntitiesService.java b/application/src/main/java/org/thingsboard/server/service/expimp/ExportableEntitiesService.java index ca401db64b..17151e3889 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/ExportableEntitiesService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/ExportableEntitiesService.java @@ -21,6 +21,8 @@ import org.thingsboard.server.common.data.id.TenantId; public interface ExportableEntitiesService { + , I extends EntityId> E findEntityById(TenantId tenantId, I id); + , I extends EntityId> E findEntityByExternalId(TenantId tenantId, I externalId); } diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/EntityExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/EntityExportService.java index bdd525d5d9..7c7fc49240 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/exp/EntityExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/EntityExportService.java @@ -21,11 +21,9 @@ import org.thingsboard.server.common.data.export.ExportableEntity; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.TenantId; -public interface EntityExportService> { +public interface EntityExportService, D extends EntityExportData> { - // FIXME: export relations - // FIXME: get rid of boilerplate - EntityExportData getExportData(TenantId tenantId, I entityId); + D getExportData(TenantId tenantId, I entityId, EntityExportSettings exportSettings); EntityType getEntityType(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/EntitiesExportResponse.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/EntityExportSettings.java similarity index 65% rename from common/data/src/main/java/org/thingsboard/server/common/data/export/EntitiesExportResponse.java rename to application/src/main/java/org/thingsboard/server/service/expimp/exp/EntityExportSettings.java index fdf08b2cdb..c70b0b2216 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/EntitiesExportResponse.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/EntityExportSettings.java @@ -13,16 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.export; +package org.thingsboard.server.service.expimp.exp; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.EntityId; - -import java.util.List; -import java.util.Map; +import lombok.NoArgsConstructor; @Data -public class EntitiesExportResponse { - private Map>>> exportData; +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class EntityExportSettings { + private boolean exportInboundRelations; } diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/AbstractEntityExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/AbstractEntityExportService.java new file mode 100644 index 0000000000..f6c2f5d5f7 --- /dev/null +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/AbstractEntityExportService.java @@ -0,0 +1,63 @@ +/** + * Copyright © 2016-2022 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.thingsboard.server.service.expimp.exp.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Lazy; +import org.thingsboard.server.common.data.export.EntityExportData; +import org.thingsboard.server.common.data.export.ExportableEntity; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.common.data.relation.EntityRelation; +import org.thingsboard.server.common.data.relation.RelationTypeGroup; +import org.thingsboard.server.dao.relation.RelationService; +import org.thingsboard.server.service.expimp.ExportableEntitiesService; +import org.thingsboard.server.service.expimp.exp.EntityExportService; +import org.thingsboard.server.service.expimp.exp.EntityExportSettings; + +import java.util.List; + +public abstract class AbstractEntityExportService, D extends EntityExportData> implements EntityExportService { + + @Autowired @Lazy + private ExportableEntitiesService exportableEntitiesService; + @Autowired + private RelationService relationService; + + + @Override + public final D getExportData(TenantId tenantId, I entityId, EntityExportSettings exportSettings) { + D exportData = newExportData(); + + E mainEntity = exportableEntitiesService.findEntityById(tenantId, entityId); + exportData.setMainEntity(mainEntity); + setRelatedEntities(tenantId, mainEntity, exportData); + if (exportSettings.isExportInboundRelations()) { + exportData.setInboundRelations(getInboundRelations(tenantId, entityId)); + } + + return exportData; + } + + protected List getInboundRelations(TenantId tenantId, I entityId) { + return relationService.findByTo(tenantId, entityId, RelationTypeGroup.COMMON); // FIXME [viacheslav]: RelationTypeGroup + } + + protected void setRelatedEntities(TenantId tenantId, E mainEntity, D exportData) {} + + protected abstract D newExportData(); + +} diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/AssetExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/AssetExportService.java index bb4b68bb29..ec1b2dddc3 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/AssetExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/AssetExportService.java @@ -15,31 +15,20 @@ */ package org.thingsboard.server.service.expimp.exp.impl; -import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; -import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.impl.AssetExportData; import org.thingsboard.server.common.data.id.AssetId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.expimp.exp.EntityExportService; @Service @TbCoreComponent -@RequiredArgsConstructor -public class AssetExportService implements EntityExportService { - - private final AssetService assetService; - +public class AssetExportService extends AbstractEntityExportService { @Override - public EntityExportData getExportData(TenantId tenantId, AssetId assetId) { - AssetExportData exportData = new AssetExportData(); - exportData.setAsset(assetService.findAssetById(tenantId, assetId)); - return exportData; + protected AssetExportData newExportData() { + return new AssetExportData(); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/CustomerExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/CustomerExportService.java index 7430f9ddd3..32e33f757c 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/CustomerExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/CustomerExportService.java @@ -15,31 +15,20 @@ */ package org.thingsboard.server.service.expimp.exp.impl; -import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.impl.CustomerExportData; import org.thingsboard.server.common.data.id.CustomerId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.customer.CustomerService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.expimp.exp.EntityExportService; @Service @TbCoreComponent -@RequiredArgsConstructor -public class CustomerExportService implements EntityExportService { - - private final CustomerService customerService; - +public class CustomerExportService extends AbstractEntityExportService { @Override - public EntityExportData getExportData(TenantId tenantId, CustomerId customerId) { - CustomerExportData exportData = new CustomerExportData(); - exportData.setCustomer(customerService.findCustomerById(tenantId, customerId)); - return exportData; + protected CustomerExportData newExportData() { + return new CustomerExportData(); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DashboardExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DashboardExportService.java index 87959429d9..be86c41c9a 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DashboardExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DashboardExportService.java @@ -15,31 +15,20 @@ */ package org.thingsboard.server.service.expimp.exp.impl; -import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.impl.DashboardExportData; import org.thingsboard.server.common.data.id.DashboardId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.dashboard.DashboardService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.expimp.exp.EntityExportService; @Service @TbCoreComponent -@RequiredArgsConstructor -public class DashboardExportService implements EntityExportService { - - private final DashboardService dashboardService; - +public class DashboardExportService extends AbstractEntityExportService { @Override - public EntityExportData getExportData(TenantId tenantId, DashboardId dashboardId) { - DashboardExportData exportData = new DashboardExportData(); - exportData.setDashboard(dashboardService.findDashboardById(tenantId, dashboardId)); - return exportData; + protected DashboardExportData newExportData() { + return new DashboardExportData(); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceExportService.java index 860aaa9b1d..c3542dc95b 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceExportService.java @@ -19,30 +19,28 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.impl.DeviceExportData; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.device.DeviceCredentialsService; -import org.thingsboard.server.dao.device.DeviceService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.expimp.exp.EntityExportService; @Service @TbCoreComponent @RequiredArgsConstructor -public class DeviceExportService implements EntityExportService { +public class DeviceExportService extends AbstractEntityExportService { - private final DeviceService deviceService; private final DeviceCredentialsService deviceCredentialsService; @Override - public EntityExportData getExportData(TenantId tenantId, DeviceId deviceId) { - DeviceExportData exportData = new DeviceExportData(); - exportData.setDevice(deviceService.findDeviceById(tenantId, deviceId)); - exportData.setCredentials(deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, deviceId)); - return exportData; + protected void setRelatedEntities(TenantId tenantId, Device device, DeviceExportData exportData) { + exportData.setCredentials(deviceCredentialsService.findDeviceCredentialsByDeviceId(TenantId.SYS_TENANT_ID, device.getId())); + } + + @Override + protected DeviceExportData newExportData() { + return new DeviceExportData(); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceProfileExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceProfileExportService.java index 425dbfd5be..03787ab30e 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceProfileExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/DeviceProfileExportService.java @@ -15,31 +15,20 @@ */ package org.thingsboard.server.service.expimp.exp.impl; -import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.impl.DeviceProfileExportData; import org.thingsboard.server.common.data.id.DeviceProfileId; -import org.thingsboard.server.common.data.id.TenantId; -import org.thingsboard.server.dao.device.DeviceProfileService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.expimp.exp.EntityExportService; @Service @TbCoreComponent -@RequiredArgsConstructor -public class DeviceProfileExportService implements EntityExportService { - - private final DeviceProfileService deviceProfileService; - +public class DeviceProfileExportService extends AbstractEntityExportService { @Override - public EntityExportData getExportData(TenantId tenantId, DeviceProfileId deviceProfileId) { - DeviceProfileExportData exportData = new DeviceProfileExportData(); - exportData.setDeviceProfile(deviceProfileService.findDeviceProfileById(tenantId, deviceProfileId)); - return exportData; + protected DeviceProfileExportData newExportData() { + return new DeviceProfileExportData(); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/RuleChainExportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/RuleChainExportService.java index 7a85281d63..0e2d24e990 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/RuleChainExportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/exp/impl/RuleChainExportService.java @@ -18,29 +18,29 @@ package org.thingsboard.server.service.expimp.exp.impl; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.export.impl.RuleChainExportData; import org.thingsboard.server.common.data.id.RuleChainId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.queue.util.TbCoreComponent; -import org.thingsboard.server.service.expimp.exp.EntityExportService; @Service @TbCoreComponent @RequiredArgsConstructor -public class RuleChainExportService implements EntityExportService { +public class RuleChainExportService extends AbstractEntityExportService { private final RuleChainService ruleChainService; @Override - public EntityExportData getExportData(TenantId tenantId, RuleChainId ruleChainId) { - RuleChainExportData exportData = new RuleChainExportData(); - exportData.setRuleChain(ruleChainService.findRuleChainById(tenantId, ruleChainId)); - exportData.setMetaData(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainId)); - return exportData; + protected void setRelatedEntities(TenantId tenantId, RuleChain ruleChain, RuleChainExportData exportData) { + exportData.setMetaData(ruleChainService.loadRuleChainMetaData(tenantId, ruleChain.getId())); + } + + @Override + protected RuleChainExportData newExportData() { + return new RuleChainExportData(); } @Override diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/imp/EntityImportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/imp/EntityImportService.java index 96a0f732ed..693ff310bf 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/imp/EntityImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/imp/EntityImportService.java @@ -23,7 +23,13 @@ import org.thingsboard.server.common.data.id.TenantId; public interface EntityImportService, D extends EntityExportData> { - EntityImportResult importEntity(TenantId tenantId, D exportData); + /* + * TODO [viacheslav]: should be as options: + * to update related entities e.g. firmware or device profile if entity already exists + * to delete current relations when importing new + * to ignore when cannot find linked entity by external id + * */ + EntityImportResult importEntity(TenantId tenantId, D exportData, EntityImportSettings importSettings); EntityType getEntityType(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/EntitiesExportRequest.java b/application/src/main/java/org/thingsboard/server/service/expimp/imp/EntityImportSettings.java similarity index 61% rename from common/data/src/main/java/org/thingsboard/server/common/data/export/EntitiesExportRequest.java rename to application/src/main/java/org/thingsboard/server/service/expimp/imp/EntityImportSettings.java index d3502695c0..1b29139e6b 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/EntitiesExportRequest.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/imp/EntityImportSettings.java @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.thingsboard.server.common.data.export; +package org.thingsboard.server.service.expimp.imp; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; -import org.thingsboard.server.common.data.EntityType; -import org.thingsboard.server.common.data.id.EntityId; - -import java.util.List; -import java.util.Map; +import lombok.NoArgsConstructor; @Data -public class EntitiesExportRequest { - // todo: should be processed in a specific order, e.g. device profiles, then devices, then relations, etc. - private Map> entities; +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class EntityImportSettings { + private boolean importInboundRelations; } diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AbstractEntityImportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AbstractEntityImportService.java index fd635e239c..fd27feeea9 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AbstractEntityImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AbstractEntityImportService.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.service.expimp.imp.impl; +import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.thingsboard.server.common.data.export.EntityExportData; @@ -22,23 +23,22 @@ import org.thingsboard.server.common.data.export.ExportableEntity; import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.HasId; import org.thingsboard.server.common.data.id.TenantId; +import org.thingsboard.server.dao.relation.RelationService; import org.thingsboard.server.service.expimp.ExportableEntitiesService; import org.thingsboard.server.service.expimp.imp.EntityImportResult; import org.thingsboard.server.service.expimp.imp.EntityImportService; +import org.thingsboard.server.service.expimp.imp.EntityImportSettings; public abstract class AbstractEntityImportService, D extends EntityExportData> implements EntityImportService { @Autowired @Lazy private ExportableEntitiesService exportableEntitiesService; + @Autowired + private RelationService relationService; + - // FIXME what if exporting and importing back already exported entity ? (save version and then load it back) - /* - * export entity -> id from env1 -> import this entity -> ... - * - * maybe find not only by external id but by internal too ? but then what if we will try - * */ @Override - public final EntityImportResult importEntity(TenantId tenantId, D exportData) { + public final EntityImportResult importEntity(TenantId tenantId, D exportData, EntityImportSettings importSettings) { E entity = exportData.getMainEntity(); E existingEntity = findByExternalId(tenantId, entity.getId()); @@ -51,7 +51,18 @@ public abstract class AbstractEntityImportService { + relation.setTo(savedEntity.getId()); + relation.setFrom(getInternalId(tenantId, relation.getFrom())); + relationService.saveRelation(tenantId, relation); + }); + } EntityImportResult importResult = new EntityImportResult<>(); importResult.setSavedEntity(savedEntity); @@ -59,17 +70,14 @@ public abstract class AbstractEntityImportService ID getInternalId(TenantId tenantId, ID externalId) { if (externalId == null) { return null; diff --git a/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AssetImportService.java b/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AssetImportService.java index 4e6fa2b33e..f228b9be5e 100644 --- a/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AssetImportService.java +++ b/application/src/main/java/org/thingsboard/server/service/expimp/imp/impl/AssetImportService.java @@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.id.AssetId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.asset.AssetService; import org.thingsboard.server.queue.util.TbCoreComponent; +import org.thingsboard.server.service.expimp.imp.EntityImportSettings; @Service @TbCoreComponent @@ -34,7 +35,7 @@ public class AssetImportService extends AbstractEntityImportService { // ruleChainConnectionInfo.setTargetRuleChainId(); - // TODO: check if this thing is needed for "Other Rule Chain Node" - // TODO: and check import of tenant rule chains + // TODO [viacheslav]: check if this thing is needed for "Other Rule Chain Node" + // TODO [viacheslav]: and check import of tenant rule chains }); ruleChainService.saveRuleChainMetaData(tenantId, metaData); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java index f87b44b0eb..c2f23a030f 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/Customer.java @@ -40,7 +40,7 @@ public class Customer extends ContactBased implements HasTenantId, E private TenantId tenantId; @Getter @Setter - private CustomerId externalId; // FIXME: add to hashcode, equals, etc + private CustomerId externalId; // FIXME [viacheslav]: add to hashcode, equals, etc public Customer() { super(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/EntityExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/EntityExportData.java index b428c3e6b5..261178d913 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/EntityExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/EntityExportData.java @@ -20,6 +20,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonSubTypes.Type; import com.fasterxml.jackson.annotation.JsonTypeInfo; +import lombok.Data; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.export.impl.AssetExportData; import org.thingsboard.server.common.data.export.impl.CustomerExportData; @@ -28,6 +29,9 @@ import org.thingsboard.server.common.data.export.impl.DeviceExportData; import org.thingsboard.server.common.data.export.impl.DeviceProfileExportData; import org.thingsboard.server.common.data.export.impl.RuleChainExportData; import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.relation.EntityRelation; + +import java.util.List; @JsonIgnoreProperties(ignoreUnknown = true) @JsonTypeInfo(property = "entityType", use = JsonTypeInfo.Id.NAME) @@ -39,12 +43,13 @@ import org.thingsboard.server.common.data.id.EntityId; @Type(name = "DASHBOARD", value = DashboardExportData.class), @Type(name = "CUSTOMER", value = CustomerExportData.class) }) -public interface EntityExportData> { +@Data +public abstract class EntityExportData> { - @JsonIgnore - E getMainEntity(); + private E mainEntity; + private List inboundRelations; @JsonIgnore - EntityType getEntityType(); // fixme: maybe remove if not needed + public abstract EntityType getEntityType(); } diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/ExportableEntity.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/ExportableEntity.java index 89b0cc3de7..d990652298 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/ExportableEntity.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/ExportableEntity.java @@ -15,8 +15,6 @@ */ package org.thingsboard.server.common.data.export; -import com.fasterxml.jackson.annotation.JsonIgnore; -import org.springframework.data.annotation.Transient; import org.thingsboard.server.common.data.HasName; import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.id.EntityId; @@ -25,9 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId; public interface ExportableEntity extends HasId, HasTenantId, HasName { - @Transient @JsonIgnore I getId(); - @Transient @JsonIgnore void setId(I id); I getExternalId(); diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/AssetExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/AssetExportData.java index abb268eeb6..6277a56afe 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/AssetExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/AssetExportData.java @@ -16,19 +16,14 @@ package org.thingsboard.server.common.data.export.impl; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.asset.Asset; import org.thingsboard.server.common.data.export.EntityExportData; +@EqualsAndHashCode(callSuper = true) @Data -public class AssetExportData implements EntityExportData { - - private Asset asset; - - @Override - public Asset getMainEntity() { - return asset; - } +public class AssetExportData extends EntityExportData { @Override public EntityType getEntityType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/CustomerExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/CustomerExportData.java index 02ec9e7efa..3de1dbc1b9 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/CustomerExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/CustomerExportData.java @@ -16,19 +16,14 @@ package org.thingsboard.server.common.data.export.impl; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.export.EntityExportData; +@EqualsAndHashCode(callSuper = true) @Data -public class CustomerExportData implements EntityExportData { - - private Customer customer; - - @Override - public Customer getMainEntity() { - return customer; - } +public class CustomerExportData extends EntityExportData { @Override public EntityType getEntityType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DashboardExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DashboardExportData.java index f75f2479f6..7310ad1f92 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DashboardExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DashboardExportData.java @@ -16,19 +16,14 @@ package org.thingsboard.server.common.data.export.impl; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.export.EntityExportData; +@EqualsAndHashCode(callSuper = true) @Data -public class DashboardExportData implements EntityExportData { - - private Dashboard dashboard; - - @Override - public Dashboard getMainEntity() { - return dashboard; - } +public class DashboardExportData extends EntityExportData { @Override public EntityType getEntityType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceExportData.java index ff3741dabc..7d4d404ebe 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceExportData.java @@ -16,22 +16,18 @@ package org.thingsboard.server.common.data.export.impl; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.security.DeviceCredentials; +@EqualsAndHashCode(callSuper = true) @Data -public class DeviceExportData implements EntityExportData { +public class DeviceExportData extends EntityExportData { - private Device device; private DeviceCredentials credentials; - @Override - public Device getMainEntity() { - return device; - } - @Override public EntityType getEntityType() { return EntityType.DEVICE; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceProfileExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceProfileExportData.java index a5d7872cc6..4ebae37b8e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceProfileExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/DeviceProfileExportData.java @@ -16,19 +16,14 @@ package org.thingsboard.server.common.data.export.impl; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.DeviceProfile; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.export.EntityExportData; +@EqualsAndHashCode(callSuper = true) @Data -public class DeviceProfileExportData implements EntityExportData { - - private DeviceProfile deviceProfile; - - @Override - public DeviceProfile getMainEntity() { - return deviceProfile; - } +public class DeviceProfileExportData extends EntityExportData { @Override public EntityType getEntityType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/RuleChainExportData.java b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/RuleChainExportData.java index 101f516881..d52c68b99e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/RuleChainExportData.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/export/impl/RuleChainExportData.java @@ -16,22 +16,18 @@ package org.thingsboard.server.common.data.export.impl; import lombok.Data; +import lombok.EqualsAndHashCode; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.export.EntityExportData; import org.thingsboard.server.common.data.rule.RuleChain; import org.thingsboard.server.common.data.rule.RuleChainMetaData; +@EqualsAndHashCode(callSuper = true) @Data -public class RuleChainExportData implements EntityExportData { +public class RuleChainExportData extends EntityExportData { - private RuleChain ruleChain; private RuleChainMetaData metaData; - @Override - public RuleChain getMainEntity() { - return ruleChain; - } - @Override public EntityType getEntityType() { return EntityType.RULE_CHAIN; diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/id/IdBased.java b/common/data/src/main/java/org/thingsboard/server/common/data/id/IdBased.java index cfe6918a7d..5c99ad8ddb 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/id/IdBased.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/id/IdBased.java @@ -16,33 +16,34 @@ package org.thingsboard.server.common.data.id; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonSetter; -import java.io.Serializable; import java.util.UUID; public abstract class IdBased implements HasId { protected I id; - - public IdBased() { - super(); - } - - public IdBased(I id) { - super(); - this.id = id; - } - public void setId(I id) { - this.id = id; - } + public IdBased() { + super(); + } - public I getId() { - return id; - } + public IdBased(I id) { + super(); + this.id = id; + } + + @JsonSetter + public void setId(I id) { + this.id = id; + } + + public I getId() { + return id; + } - @JsonIgnore - public UUID getUuidId() { + @JsonIgnore + public UUID getUuidId() { if (id != null) { return id.getId(); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java b/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java index c7741ec013..4e0822936b 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/ExportableEntityDao.java @@ -24,7 +24,7 @@ public interface ExportableEntityDao { T findByTenantIdAndExternalId(UUID tenantId, UUID externalId); T findByTenantIdAndId(UUID tenantId, UUID id); - // fixme: get rid of boilerplate ? + // fixme [viacheslav]: get rid of boilerplate ? EntityType getEntityType();