More tests for export/import api; improvements
This commit is contained in:
		
							parent
							
								
									a35b16d7cb
								
							
						
					
					
						commit
						c04a0ff3a6
					
				@ -17,13 +17,13 @@ package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.dao.DataAccessException;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
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.RestController;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.ExportableEntity;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
@ -41,9 +41,9 @@ import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
import org.thingsboard.server.service.sync.EntitiesExportImportService;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityFilterExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.CustomEntityFilterExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.CustomEntityQueryExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityListExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityQueryExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityTypeExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.ExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.SingleEntityExportRequest;
 | 
			
		||||
@ -71,7 +71,7 @@ public class EntitiesExportImportController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/export")
 | 
			
		||||
    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
 | 
			
		||||
    public List<EntityExportData<ExportableEntity<EntityId>>> exportEntities(@RequestBody ExportRequest exportRequest) throws ThingsboardException {
 | 
			
		||||
    public List<EntityExportData<?>> exportEntities(@RequestBody ExportRequest exportRequest) throws ThingsboardException {
 | 
			
		||||
        SecurityUser user = getCurrentUser();
 | 
			
		||||
        try {
 | 
			
		||||
            return exportEntitiesByRequest(user, exportRequest);
 | 
			
		||||
@ -82,10 +82,10 @@ public class EntitiesExportImportController extends BaseController {
 | 
			
		||||
 | 
			
		||||
    @PostMapping(value = "/export", params = {"multiple"})
 | 
			
		||||
    @PreAuthorize("hasAuthority('TENANT_ADMIN')")
 | 
			
		||||
    public List<EntityExportData<ExportableEntity<EntityId>>> exportEntities(@RequestBody List<ExportRequest> exportRequests) throws ThingsboardException {
 | 
			
		||||
    public List<EntityExportData<?>> exportEntities(@RequestBody List<ExportRequest> exportRequests) throws ThingsboardException {
 | 
			
		||||
        SecurityUser user = getCurrentUser();
 | 
			
		||||
        try {
 | 
			
		||||
            List<EntityExportData<ExportableEntity<EntityId>>> exportDataList = new ArrayList<>();
 | 
			
		||||
            List<EntityExportData<?>> exportDataList = new ArrayList<>();
 | 
			
		||||
            for (ExportRequest exportRequest : exportRequests) {
 | 
			
		||||
                exportDataList.addAll(exportEntitiesByRequest(user, exportRequest));
 | 
			
		||||
            }
 | 
			
		||||
@ -96,10 +96,10 @@ public class EntitiesExportImportController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private List<EntityExportData<ExportableEntity<EntityId>>> exportEntitiesByRequest(SecurityUser user, ExportRequest request) throws ThingsboardException {
 | 
			
		||||
    private List<EntityExportData<?>> exportEntitiesByRequest(SecurityUser user, ExportRequest request) throws ThingsboardException {
 | 
			
		||||
        List<EntityId> entitiesIds = findEntitiesForRequest(user, request);
 | 
			
		||||
 | 
			
		||||
        List<EntityExportData<ExportableEntity<EntityId>>> exportDataList = new ArrayList<>();
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = new ArrayList<>();
 | 
			
		||||
        for (EntityId entityId : entitiesIds) {
 | 
			
		||||
            exportDataList.add(exportImportService.exportEntity(user, entityId, request.getExportSettings()));
 | 
			
		||||
        }
 | 
			
		||||
@ -122,15 +122,15 @@ public class EntitiesExportImportController extends BaseController {
 | 
			
		||||
                CustomerId customerId = Optional.ofNullable(exportRequest.getCustomerId()).orElse(emptyId(EntityType.CUSTOMER));
 | 
			
		||||
                return findEntitiesByFilter(user.getTenantId(), customerId, entityTypeFilter, exportRequest.getPage(), exportRequest.getPageSize());
 | 
			
		||||
            }
 | 
			
		||||
            case ENTITY_FILTER: {
 | 
			
		||||
                EntityFilterExportRequest exportRequest = (EntityFilterExportRequest) request;
 | 
			
		||||
            case CUSTOM_ENTITY_FILTER: {
 | 
			
		||||
                CustomEntityFilterExportRequest exportRequest = (CustomEntityFilterExportRequest) request;
 | 
			
		||||
                EntityFilter filter = exportRequest.getFilter();
 | 
			
		||||
 | 
			
		||||
                CustomerId customerId = Optional.ofNullable(exportRequest.getCustomerId()).orElse(emptyId(EntityType.CUSTOMER));
 | 
			
		||||
                return findEntitiesByFilter(user.getTenantId(), customerId, filter, exportRequest.getPage(), exportRequest.getPageSize());
 | 
			
		||||
            }
 | 
			
		||||
            case ENTITY_QUERY:{
 | 
			
		||||
                EntityQueryExportRequest exportRequest = (EntityQueryExportRequest) request;
 | 
			
		||||
            case CUSTOM_ENTITY_QUERY: {
 | 
			
		||||
                CustomEntityQueryExportRequest exportRequest = (CustomEntityQueryExportRequest) request;
 | 
			
		||||
                EntityDataQuery query = exportRequest.getQuery();
 | 
			
		||||
 | 
			
		||||
                CustomerId customerId = Optional.ofNullable(exportRequest.getCustomerId()).orElse(emptyId(EntityType.CUSTOMER));
 | 
			
		||||
@ -153,24 +153,29 @@ public class EntitiesExportImportController extends BaseController {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private List<EntityId> findEntitiesByQuery(TenantId tenantId, CustomerId customerId, EntityDataQuery query) {
 | 
			
		||||
        return entityService.findEntityDataByQuery(tenantId, customerId, query).getData().stream()
 | 
			
		||||
                .map(EntityData::getEntityId)
 | 
			
		||||
                .collect(Collectors.toList());
 | 
			
		||||
        try {
 | 
			
		||||
            return entityService.findEntityDataByQuery(tenantId, customerId, query).getData().stream()
 | 
			
		||||
                    .map(EntityData::getEntityId)
 | 
			
		||||
                    .collect(Collectors.toList());
 | 
			
		||||
        } catch (DataAccessException e) {
 | 
			
		||||
            log.error("Failed to find entity data by query: {}", e.getMessage());
 | 
			
		||||
            throw new IllegalArgumentException("Entity filter cannot be processed");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/import")
 | 
			
		||||
    public List<EntityImportResult<ExportableEntity<EntityId>>> importEntities(@RequestBody ImportRequest importRequest) throws ThingsboardException {
 | 
			
		||||
    public List<EntityImportResult<?>> importEntities(@RequestBody ImportRequest importRequest) throws ThingsboardException {
 | 
			
		||||
        SecurityUser user = getCurrentUser();
 | 
			
		||||
        try {
 | 
			
		||||
            List<EntityImportResult<ExportableEntity<EntityId>>> importResults = exportImportService.importEntities(user, importRequest.getExportDataList(), importRequest.getImportSettings());
 | 
			
		||||
            List<EntityImportResult<?>> importResults = exportImportService.importEntities(user, importRequest.getExportDataList(), importRequest.getImportSettings());
 | 
			
		||||
 | 
			
		||||
            importResults.stream()
 | 
			
		||||
                    .map(EntityImportResult::getPushEventsCallback)
 | 
			
		||||
                    .map(EntityImportResult::getSendEventsCallback)
 | 
			
		||||
                    .filter(Objects::nonNull)
 | 
			
		||||
                    .forEach(pushEventsCallback -> {
 | 
			
		||||
                    .forEach(sendEventsCallback -> {
 | 
			
		||||
                        try {
 | 
			
		||||
                            pushEventsCallback.run();
 | 
			
		||||
                            sendEventsCallback.run();
 | 
			
		||||
                        } catch (Exception e) {
 | 
			
		||||
                            log.error("Failed to send event for entity", e);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
@ -67,7 +67,7 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
 | 
			
		||||
 | 
			
		||||
    protected static final List<EntityType> SUPPORTED_ENTITY_TYPES = List.of(
 | 
			
		||||
            EntityType.CUSTOMER, EntityType.ASSET, EntityType.RULE_CHAIN,
 | 
			
		||||
            EntityType.DEVICE_PROFILE, EntityType.DEVICE, EntityType.DASHBOARD
 | 
			
		||||
            EntityType.DASHBOARD, EntityType.DEVICE_PROFILE, EntityType.DEVICE
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -82,12 +82,12 @@ public class DefaultEntitiesExportImportService implements EntitiesExportImportS
 | 
			
		||||
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<EntityImportResult<ExportableEntity<EntityId>>> importEntities(SecurityUser user, List<EntityExportData<ExportableEntity<EntityId>>> exportDataList, EntityImportSettings importSettings) throws ThingsboardException {
 | 
			
		||||
    public List<EntityImportResult<?>> importEntities(SecurityUser user, List<EntityExportData<?>> exportDataList, EntityImportSettings importSettings) throws ThingsboardException {
 | 
			
		||||
        exportDataList.sort(Comparator.comparing(exportData -> SUPPORTED_ENTITY_TYPES.indexOf(exportData.getEntityType())));
 | 
			
		||||
        List<EntityImportResult<ExportableEntity<EntityId>>> importResults = new ArrayList<>();
 | 
			
		||||
        List<EntityImportResult<?>> importResults = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        for (EntityExportData<ExportableEntity<EntityId>> exportData : exportDataList) {
 | 
			
		||||
            EntityImportResult<ExportableEntity<EntityId>> importResult = importEntity(user, exportData, importSettings);
 | 
			
		||||
        for (EntityExportData exportData : exportDataList) {
 | 
			
		||||
            EntityImportResult<?> importResult = importEntity(user, exportData, importSettings);
 | 
			
		||||
            importResults.add(importResult);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,6 @@ public interface EntitiesExportImportService {
 | 
			
		||||
 | 
			
		||||
    <E extends ExportableEntity<I>, I extends EntityId> EntityExportData<E> exportEntity(SecurityUser user, I entityId, EntityExportSettings exportSettings) throws ThingsboardException;
 | 
			
		||||
 | 
			
		||||
    List<EntityImportResult<ExportableEntity<EntityId>>> importEntities(SecurityUser user, List<EntityExportData<ExportableEntity<EntityId>>> exportDataList, EntityImportSettings importSettings) throws ThingsboardException;
 | 
			
		||||
    List<EntityImportResult<?>> importEntities(SecurityUser user, List<EntityExportData<?>> exportDataList, EntityImportSettings importSettings) throws ThingsboardException;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,21 +21,16 @@ 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.Customer;
 | 
			
		||||
import org.thingsboard.server.common.data.Dashboard;
 | 
			
		||||
import org.thingsboard.server.common.data.Device;
 | 
			
		||||
import org.thingsboard.server.common.data.DeviceProfile;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.ExportableEntity;
 | 
			
		||||
import org.thingsboard.server.common.data.asset.Asset;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.EntityRelation;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
			
		||||
import org.thingsboard.server.utils.JsonTbEntity;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@JsonIgnoreProperties(ignoreUnknown = true)
 | 
			
		||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", defaultImpl = EntityExportData.class, visible = true)
 | 
			
		||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", defaultImpl = EntityExportData.class)
 | 
			
		||||
@JsonSubTypes({
 | 
			
		||||
        @Type(name = "DEVICE", value = DeviceExportData.class),
 | 
			
		||||
        @Type(name = "RULE_CHAIN", value = RuleChainExportData.class)
 | 
			
		||||
@ -44,15 +39,7 @@ import java.util.List;
 | 
			
		||||
@Data
 | 
			
		||||
public class EntityExportData<E extends ExportableEntity<? extends EntityId>> {
 | 
			
		||||
 | 
			
		||||
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
 | 
			
		||||
    @JsonSubTypes({
 | 
			
		||||
            @Type(name = "DEVICE", value = Device.class),
 | 
			
		||||
            @Type(name = "RULE_CHAIN", value = RuleChain.class),
 | 
			
		||||
            @Type(name = "DEVICE_PROFILE", value = DeviceProfile.class),
 | 
			
		||||
            @Type(name = "ASSET", value = Asset.class),
 | 
			
		||||
            @Type(name = "DASHBOARD", value = Dashboard.class),
 | 
			
		||||
            @Type(name = "CUSTOMER", value = Customer.class)
 | 
			
		||||
    })
 | 
			
		||||
    @JsonTbEntity
 | 
			
		||||
    private E entity;
 | 
			
		||||
    private EntityType entityType;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,7 @@ import org.thingsboard.server.common.data.query.EntityFilter;
 | 
			
		||||
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Data
 | 
			
		||||
public class EntityFilterExportRequest extends ExportRequest {
 | 
			
		||||
public class CustomEntityFilterExportRequest extends ExportRequest {
 | 
			
		||||
 | 
			
		||||
    private EntityFilter filter;
 | 
			
		||||
    private int page;
 | 
			
		||||
@ -31,7 +31,7 @@ public class EntityFilterExportRequest extends ExportRequest {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ExportRequestType getType() {
 | 
			
		||||
        return ExportRequestType.ENTITY_FILTER;
 | 
			
		||||
        return ExportRequestType.CUSTOM_ENTITY_FILTER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -22,14 +22,14 @@ import org.thingsboard.server.common.data.query.EntityDataQuery;
 | 
			
		||||
 | 
			
		||||
@EqualsAndHashCode(callSuper = true)
 | 
			
		||||
@Data
 | 
			
		||||
public class EntityQueryExportRequest extends ExportRequest {
 | 
			
		||||
public class CustomEntityQueryExportRequest extends ExportRequest {
 | 
			
		||||
 | 
			
		||||
    private EntityDataQuery query;
 | 
			
		||||
    private CustomerId customerId;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ExportRequestType getType() {
 | 
			
		||||
        return ExportRequestType.ENTITY_QUERY;
 | 
			
		||||
        return ExportRequestType.CUSTOM_ENTITY_QUERY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -15,7 +15,6 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.service.sync.exporting.data.request;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
 | 
			
		||||
@ -27,15 +26,14 @@ import lombok.Data;
 | 
			
		||||
        @Type(name = "SINGLE_ENTITY", value = SingleEntityExportRequest.class),
 | 
			
		||||
        @Type(name = "ENTITY_LIST", value = EntityListExportRequest.class),
 | 
			
		||||
        @Type(name = "ENTITY_TYPE", value = EntityTypeExportRequest.class),
 | 
			
		||||
        @Type(name = "ENTITY_FILTER", value = EntityFilterExportRequest.class),
 | 
			
		||||
        @Type(name = "ENTITY_QUERY", value = EntityQueryExportRequest.class)
 | 
			
		||||
        @Type(name = "CUSTOM_ENTITY_FILTER", value = CustomEntityFilterExportRequest.class),
 | 
			
		||||
        @Type(name = "CUSTOM_ENTITY_QUERY", value = CustomEntityQueryExportRequest.class)
 | 
			
		||||
})
 | 
			
		||||
@Data
 | 
			
		||||
public abstract class ExportRequest {
 | 
			
		||||
 | 
			
		||||
    private EntityExportSettings exportSettings;
 | 
			
		||||
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    public abstract ExportRequestType getType();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,6 @@ public enum ExportRequestType {
 | 
			
		||||
    ENTITY_LIST,
 | 
			
		||||
    ENTITY_TYPE,
 | 
			
		||||
 | 
			
		||||
    ENTITY_FILTER,
 | 
			
		||||
    ENTITY_QUERY
 | 
			
		||||
    CUSTOM_ENTITY_FILTER,
 | 
			
		||||
    CUSTOM_ENTITY_QUERY
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -16,32 +16,33 @@
 | 
			
		||||
package org.thingsboard.server.service.sync.importing.data;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
import lombok.Setter;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.ExportableEntity;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.utils.JsonTbEntity;
 | 
			
		||||
import org.thingsboard.server.utils.ThrowingRunnable;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class EntityImportResult<E extends ExportableEntity<? extends EntityId>> {
 | 
			
		||||
    @Getter @Setter
 | 
			
		||||
 | 
			
		||||
    @JsonTbEntity
 | 
			
		||||
    private E savedEntity;
 | 
			
		||||
    @Getter @Setter
 | 
			
		||||
    @JsonTbEntity
 | 
			
		||||
    private E oldEntity;
 | 
			
		||||
    @Getter @Setter
 | 
			
		||||
    private EntityType entityType;
 | 
			
		||||
 | 
			
		||||
    @Getter @JsonIgnore
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    private ThrowingRunnable saveReferencesCallback = () -> {};
 | 
			
		||||
    @Getter @JsonIgnore
 | 
			
		||||
    private ThrowingRunnable pushEventsCallback = () -> {};
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    private ThrowingRunnable sendEventsCallback = () -> {};
 | 
			
		||||
 | 
			
		||||
    public void addSaveReferencesCallback(ThrowingRunnable callback) {
 | 
			
		||||
        this.saveReferencesCallback = this.saveReferencesCallback.andThen(callback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void addPushEventsCallback(ThrowingRunnable callback) {
 | 
			
		||||
        this.pushEventsCallback = this.pushEventsCallback.andThen(callback);
 | 
			
		||||
    public void addSendEventsCallback(ThrowingRunnable callback) {
 | 
			
		||||
        this.sendEventsCallback = this.sendEventsCallback.andThen(callback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,8 +26,10 @@ import lombok.NoArgsConstructor;
 | 
			
		||||
@Builder
 | 
			
		||||
public class EntityImportSettings {
 | 
			
		||||
    private boolean findExistingByName;
 | 
			
		||||
 | 
			
		||||
    private boolean importInboundRelations;
 | 
			
		||||
    private boolean importOutboundRelations;
 | 
			
		||||
    private boolean removeExistingRelations;
 | 
			
		||||
 | 
			
		||||
    private boolean updateReferencesToOtherEntities;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@ import java.util.List;
 | 
			
		||||
@Data
 | 
			
		||||
public class ImportRequest {
 | 
			
		||||
 | 
			
		||||
    private List<EntityExportData<ExportableEntity<EntityId>>> exportDataList;
 | 
			
		||||
    private List<EntityExportData<?>> exportDataList;
 | 
			
		||||
    private EntityImportSettings importSettings;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -21,7 +21,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.context.annotation.Lazy;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
import org.thingsboard.server.cluster.TbClusterService;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.ExportableEntity;
 | 
			
		||||
import org.thingsboard.server.common.data.HasCustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
			
		||||
@ -76,6 +75,7 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
 | 
			
		||||
            exportableEntitiesService.checkPermission(user, entity, getEntityType(), Operation.CREATE);
 | 
			
		||||
        } else {
 | 
			
		||||
            entity.setId(existingEntity.getId());
 | 
			
		||||
            entity.setCreatedTime(existingEntity.getCreatedTime());
 | 
			
		||||
            exportableEntitiesService.checkPermission(user, existingEntity, getEntityType(), Operation.WRITE);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -146,7 +146,7 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        importResult.addPushEventsCallback(() -> {
 | 
			
		||||
        importResult.addSendEventsCallback(() -> {
 | 
			
		||||
            onEntitySaved(user, savedEntity, oldEntity);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@ -172,8 +172,6 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private <ID extends EntityId> HasId<ID> findInternalEntity(TenantId tenantId, ID externalId) {
 | 
			
		||||
        if (externalId == null || externalId.isNullUid()) return null;
 | 
			
		||||
 | 
			
		||||
        return (HasId<ID>) Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndExternalId(tenantId, externalId))
 | 
			
		||||
                .or(() -> Optional.ofNullable(exportableEntitiesService.findEntityByTenantIdAndId(tenantId, externalId)))
 | 
			
		||||
                .orElseThrow(() -> new IllegalArgumentException("Cannot find " + externalId.getEntityType() + " by external id " + externalId));
 | 
			
		||||
@ -187,19 +185,18 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
 | 
			
		||||
        private final E existingEntity;
 | 
			
		||||
        private final EntityImportSettings importSettings;
 | 
			
		||||
 | 
			
		||||
        private final Set<EntityType> ALWAYS_UPDATE_REFERENCED_IDS = Set.of(
 | 
			
		||||
                EntityType.RULE_CHAIN
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        public <ID extends EntityId> ID get(Function<E, ID> idExtractor) {
 | 
			
		||||
            if (existingEntity == null || importSettings.isUpdateReferencesToOtherEntities()
 | 
			
		||||
                    || ALWAYS_UPDATE_REFERENCED_IDS.contains(getEntityType())) {
 | 
			
		||||
            if (existingEntity == null || importSettings.isUpdateReferencesToOtherEntities()) {
 | 
			
		||||
                return getInternalId(idExtractor.apply(this.entity));
 | 
			
		||||
            } else {
 | 
			
		||||
                return idExtractor.apply(existingEntity);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public <ID extends EntityId> ID getInternal(ID externalId) {
 | 
			
		||||
            return getInternalId(externalId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public <ID extends EntityId, T> Set<T> get(Function<E, Set<T>> listExtractor, Function<T, ID> idGetter, BiConsumer<T, ID> idSetter) {
 | 
			
		||||
            if (existingEntity == null || importSettings.isUpdateReferencesToOtherEntities()) {
 | 
			
		||||
                return Optional.ofNullable(listExtractor.apply(entity)).orElse(Collections.emptySet()).stream()
 | 
			
		||||
@ -213,17 +210,15 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private <ID extends EntityId> ID getInternalId(ID externalId) {
 | 
			
		||||
            if (externalId == null || externalId.isNullUid()) return null;
 | 
			
		||||
 | 
			
		||||
            HasId<ID> entity = findInternalEntity(user.getTenantId(), externalId);
 | 
			
		||||
            if (entity != null) {
 | 
			
		||||
                try {
 | 
			
		||||
                    exportableEntitiesService.checkPermission(user, entity, entity.getId().getEntityType(), Operation.READ);
 | 
			
		||||
                } catch (ThingsboardException e) {
 | 
			
		||||
                    throw new IllegalArgumentException(e.getMessage(), e);
 | 
			
		||||
                }
 | 
			
		||||
                return entity.getId();
 | 
			
		||||
            } else {
 | 
			
		||||
                return null;
 | 
			
		||||
            try {
 | 
			
		||||
                exportableEntitiesService.checkPermission(user, entity, entity.getId().getEntityType(), Operation.READ);
 | 
			
		||||
            } catch (ThingsboardException e) {
 | 
			
		||||
                throw new IllegalArgumentException(e.getMessage(), e);
 | 
			
		||||
            }
 | 
			
		||||
            return entity.getId();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -74,7 +74,7 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
 | 
			
		||||
                                String newFilterJson = UUID_PATTERN.matcher(filterJson).replaceAll(matchResult -> {
 | 
			
		||||
                                    String uuid = matchResult.group();
 | 
			
		||||
                                    EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, uuid);
 | 
			
		||||
                                    return idProvider.get(d -> entityId).toString();
 | 
			
		||||
                                    return idProvider.getInternal(entityId).toString();
 | 
			
		||||
                                });
 | 
			
		||||
                                ((ObjectNode) entityAlias).set("filter", JacksonUtil.toJsonNode(newFilterJson));
 | 
			
		||||
                            });
 | 
			
		||||
@ -86,7 +86,7 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
 | 
			
		||||
            dashboard.setAssignedCustomers(null);
 | 
			
		||||
            dashboard = dashboardService.saveDashboard(dashboard);
 | 
			
		||||
            for (ShortCustomerInfo customerInfo : assignedCustomers) {
 | 
			
		||||
                dashboardService.assignDashboardToCustomer(tenantId, dashboard.getId(), customerInfo.getCustomerId());
 | 
			
		||||
                dashboard = dashboardService.assignDashboardToCustomer(tenantId, dashboard.getId(), customerInfo.getCustomerId());
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            Set<CustomerId> existingAssignedCustomers = Optional.ofNullable(dashboardService.findDashboardById(tenantId, dashboard.getId()).getAssignedCustomers())
 | 
			
		||||
 | 
			
		||||
@ -63,14 +63,14 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
 | 
			
		||||
                            .map(JsonNode::asText).map(UUID::fromString)
 | 
			
		||||
                            .ifPresent(otherRuleChainUuid -> {
 | 
			
		||||
                                ((ObjectNode) ruleNodeConfig).set("ruleChainId", new TextNode(
 | 
			
		||||
                                        idProvider.get(rc -> new RuleChainId(otherRuleChainUuid)).toString()
 | 
			
		||||
                                        idProvider.getInternal(new RuleChainId(otherRuleChainUuid)).toString()
 | 
			
		||||
                                ));
 | 
			
		||||
                                ruleNode.setConfiguration(ruleNodeConfig);
 | 
			
		||||
                            });
 | 
			
		||||
                });
 | 
			
		||||
        Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
 | 
			
		||||
                .forEach(ruleChainConnectionInfo -> {
 | 
			
		||||
                    ruleChainConnectionInfo.setTargetRuleChainId(idProvider.get(rc -> ruleChainConnectionInfo.getTargetRuleChainId()));
 | 
			
		||||
                    ruleChainConnectionInfo.setTargetRuleChainId(idProvider.getInternal(ruleChainConnectionInfo.getTargetRuleChainId()));
 | 
			
		||||
                });
 | 
			
		||||
        ruleChain.setFirstRuleNodeId(null);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,47 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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.utils;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
 | 
			
		||||
import org.thingsboard.server.common.data.Customer;
 | 
			
		||||
import org.thingsboard.server.common.data.Dashboard;
 | 
			
		||||
import org.thingsboard.server.common.data.Device;
 | 
			
		||||
import org.thingsboard.server.common.data.DeviceProfile;
 | 
			
		||||
import org.thingsboard.server.common.data.asset.Asset;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
			
		||||
 | 
			
		||||
import java.lang.annotation.ElementType;
 | 
			
		||||
import java.lang.annotation.Retention;
 | 
			
		||||
import java.lang.annotation.RetentionPolicy;
 | 
			
		||||
import java.lang.annotation.Target;
 | 
			
		||||
 | 
			
		||||
@Retention(RetentionPolicy.RUNTIME)
 | 
			
		||||
@Target(ElementType.FIELD)
 | 
			
		||||
@JacksonAnnotationsInside
 | 
			
		||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "entityType", include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
 | 
			
		||||
@JsonSubTypes({
 | 
			
		||||
        @Type(name = "DEVICE", value = Device.class),
 | 
			
		||||
        @Type(name = "RULE_CHAIN", value = RuleChain.class),
 | 
			
		||||
        @Type(name = "DEVICE_PROFILE", value = DeviceProfile.class),
 | 
			
		||||
        @Type(name = "ASSET", value = Asset.class),
 | 
			
		||||
        @Type(name = "DASHBOARD", value = Dashboard.class),
 | 
			
		||||
        @Type(name = "CUSTOMER", value = Customer.class)
 | 
			
		||||
})
 | 
			
		||||
public @interface JsonTbEntity {
 | 
			
		||||
}
 | 
			
		||||
@ -17,6 +17,8 @@ package org.thingsboard.server.controller;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.core.type.TypeReference;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.TextNode;
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.test.web.servlet.ResultActions;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
@ -28,6 +30,10 @@ import org.thingsboard.server.common.data.DeviceProfile;
 | 
			
		||||
import org.thingsboard.server.common.data.DeviceProfileType;
 | 
			
		||||
import org.thingsboard.server.common.data.DeviceTransportType;
 | 
			
		||||
import org.thingsboard.server.common.data.ExportableEntity;
 | 
			
		||||
import org.thingsboard.server.common.data.HasTenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.OtaPackage;
 | 
			
		||||
import org.thingsboard.server.common.data.Tenant;
 | 
			
		||||
import org.thingsboard.server.common.data.User;
 | 
			
		||||
import org.thingsboard.server.common.data.asset.Asset;
 | 
			
		||||
import org.thingsboard.server.common.data.device.data.DefaultDeviceTransportConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.device.data.DeviceData;
 | 
			
		||||
@ -35,19 +41,29 @@ import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileCon
 | 
			
		||||
import org.thingsboard.server.common.data.device.profile.DefaultDeviceProfileTransportConfiguration;
 | 
			
		||||
import org.thingsboard.server.common.data.device.profile.DeviceProfileData;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DashboardId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DeviceProfileId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.RuleChainId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.ota.ChecksumAlgorithm;
 | 
			
		||||
import org.thingsboard.server.common.data.ota.OtaPackageType;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.EntityRelation;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChainType;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNode;
 | 
			
		||||
import org.thingsboard.server.common.data.security.Authority;
 | 
			
		||||
import org.thingsboard.server.dao.asset.AssetService;
 | 
			
		||||
import org.thingsboard.server.dao.customer.CustomerService;
 | 
			
		||||
import org.thingsboard.server.dao.dashboard.DashboardService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceProfileService;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceService;
 | 
			
		||||
import org.thingsboard.server.dao.ota.OtaPackageService;
 | 
			
		||||
import org.thingsboard.server.dao.relation.RelationService;
 | 
			
		||||
import org.thingsboard.server.dao.rule.RuleChainService;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantService;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityExportSettings;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.ExportRequest;
 | 
			
		||||
@ -56,11 +72,12 @@ import org.thingsboard.server.service.sync.importing.data.EntityImportResult;
 | 
			
		||||
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
 | 
			
		||||
import org.thingsboard.server.service.sync.importing.data.request.ImportRequest;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Type;
 | 
			
		||||
import java.nio.ByteBuffer;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 | 
			
		||||
 | 
			
		||||
public abstract class BaseEntitiesExportImportControllerTest extends AbstractControllerTest {
 | 
			
		||||
@ -68,6 +85,8 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected DeviceService deviceService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected OtaPackageService otaPackageService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected DeviceProfileService deviceProfileService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected AssetService assetService;
 | 
			
		||||
@ -77,6 +96,45 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
    protected RuleChainService ruleChainService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected DashboardService dashboardService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected RelationService relationService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    protected TenantService tenantService;
 | 
			
		||||
 | 
			
		||||
    protected TenantId tenantId1;
 | 
			
		||||
    protected User tenantAdmin1;
 | 
			
		||||
 | 
			
		||||
    protected TenantId tenantId2;
 | 
			
		||||
    protected User tenantAdmin2;
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    public void beforeEach() throws Exception {
 | 
			
		||||
        loginSysAdmin();
 | 
			
		||||
        Tenant tenant1 = new Tenant();
 | 
			
		||||
        tenant1.setTitle("Tenant 1");
 | 
			
		||||
        tenant1.setEmail("tenant1@thingsboard.org");
 | 
			
		||||
        this.tenantId1 = tenantService.saveTenant(tenant1).getId();
 | 
			
		||||
        User tenantAdmin1 = new User();
 | 
			
		||||
        tenantAdmin1.setTenantId(tenantId1);
 | 
			
		||||
        tenantAdmin1.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        tenantAdmin1.setEmail("tenant1-admin@thingsboard.org");
 | 
			
		||||
        this.tenantAdmin1 = createUser(tenantAdmin1, "12345678");
 | 
			
		||||
        Tenant tenant2 = new Tenant();
 | 
			
		||||
        tenant2.setTitle("Tenant 2");
 | 
			
		||||
        tenant2.setEmail("tenant2@thingsboard.org");
 | 
			
		||||
        this.tenantId2 = tenantService.saveTenant(tenant2).getId();
 | 
			
		||||
        User tenantAdmin2 = new User();
 | 
			
		||||
        tenantAdmin2.setTenantId(tenantId2);
 | 
			
		||||
        tenantAdmin2.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        tenantAdmin2.setEmail("tenant2-admin@thingsboard.org");
 | 
			
		||||
        this.tenantAdmin2 = createUser(tenantAdmin2, "12345678");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @After
 | 
			
		||||
    public void afterEach() {
 | 
			
		||||
        tenantService.deleteTenant(tenantId1);
 | 
			
		||||
        tenantService.deleteTenant(tenantId2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected Device createDevice(TenantId tenantId, CustomerId customerId, DeviceProfileId deviceProfileId, String name) {
 | 
			
		||||
        Device device = new Device();
 | 
			
		||||
@ -91,13 +149,38 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        return deviceService.saveDevice(device);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected DeviceProfile createDeviceProfile(TenantId tenantId, String name) {
 | 
			
		||||
    protected OtaPackage createOtaPackage(TenantId tenantId, DeviceProfileId deviceProfileId, OtaPackageType type) {
 | 
			
		||||
        OtaPackage otaPackage = new OtaPackage();
 | 
			
		||||
        otaPackage.setTenantId(tenantId);
 | 
			
		||||
        otaPackage.setDeviceProfileId(deviceProfileId);
 | 
			
		||||
        otaPackage.setType(type);
 | 
			
		||||
        otaPackage.setTitle("My " + type);
 | 
			
		||||
        otaPackage.setVersion("v1.0");
 | 
			
		||||
        otaPackage.setFileName("filename.txt");
 | 
			
		||||
        otaPackage.setContentType("text/plain");
 | 
			
		||||
        otaPackage.setChecksumAlgorithm(ChecksumAlgorithm.SHA256);
 | 
			
		||||
        otaPackage.setChecksum("4bf5122f344554c53bde2ebb8cd2b7e3d1600ad631c385a5d7cce23c7785459a");
 | 
			
		||||
        otaPackage.setDataSize(1L);
 | 
			
		||||
        otaPackage.setData(ByteBuffer.wrap(new byte[]{(int) 1}));
 | 
			
		||||
        return otaPackageService.saveOtaPackage(otaPackage);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void checkImportedDeviceData(Device initialDevice, Device importedDevice) {
 | 
			
		||||
        assertThat(importedDevice.getName()).isEqualTo(initialDevice.getName());
 | 
			
		||||
        assertThat(importedDevice.getType()).isEqualTo(initialDevice.getType());
 | 
			
		||||
        assertThat(importedDevice.getDeviceData()).isEqualTo(initialDevice.getDeviceData());
 | 
			
		||||
        assertThat(importedDevice.getLabel()).isEqualTo(initialDevice.getLabel());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected DeviceProfile createDeviceProfile(TenantId tenantId, RuleChainId defaultRuleChainId, DashboardId defaultDashboardId, String name) {
 | 
			
		||||
        DeviceProfile deviceProfile = new DeviceProfile();
 | 
			
		||||
        deviceProfile.setTenantId(tenantId);
 | 
			
		||||
        deviceProfile.setName(name);
 | 
			
		||||
        deviceProfile.setDescription("dscrptn");
 | 
			
		||||
        deviceProfile.setType(DeviceProfileType.DEFAULT);
 | 
			
		||||
        deviceProfile.setTransportType(DeviceTransportType.DEFAULT);
 | 
			
		||||
        deviceProfile.setDefaultRuleChainId(defaultRuleChainId);
 | 
			
		||||
        deviceProfile.setDefaultDashboardId(defaultDashboardId);
 | 
			
		||||
        DeviceProfileData profileData = new DeviceProfileData();
 | 
			
		||||
        profileData.setConfiguration(new DefaultDeviceProfileConfiguration());
 | 
			
		||||
        profileData.setTransportConfiguration(new DefaultDeviceProfileTransportConfiguration());
 | 
			
		||||
@ -105,6 +188,14 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        return deviceProfileService.saveDeviceProfile(deviceProfile);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void checkImportedDeviceProfileData(DeviceProfile initialProfile, DeviceProfile importedProfile) {
 | 
			
		||||
        assertThat(initialProfile.getName()).isEqualTo(importedProfile.getName());
 | 
			
		||||
        assertThat(initialProfile.getType()).isEqualTo(importedProfile.getType());
 | 
			
		||||
        assertThat(initialProfile.getTransportType()).isEqualTo(importedProfile.getTransportType());
 | 
			
		||||
        assertThat(initialProfile.getProfileData()).isEqualTo(importedProfile.getProfileData());
 | 
			
		||||
        assertThat(initialProfile.getDescription()).isEqualTo(importedProfile.getDescription());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected Asset createAsset(TenantId tenantId, CustomerId customerId, String type, String name) {
 | 
			
		||||
        Asset asset = new Asset();
 | 
			
		||||
        asset.setTenantId(tenantId);
 | 
			
		||||
@ -116,6 +207,13 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        return assetService.saveAsset(asset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void checkImportedAssetData(Asset initialAsset, Asset importedAsset) {
 | 
			
		||||
        assertThat(importedAsset.getName()).isEqualTo(initialAsset.getName());
 | 
			
		||||
        assertThat(importedAsset.getType()).isEqualTo(initialAsset.getType());
 | 
			
		||||
        assertThat(importedAsset.getLabel()).isEqualTo(initialAsset.getLabel());
 | 
			
		||||
        assertThat(importedAsset.getAdditionalInfo()).isEqualTo(initialAsset.getAdditionalInfo());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected Customer createCustomer(TenantId tenantId, String name) {
 | 
			
		||||
        Customer customer = new Customer();
 | 
			
		||||
        customer.setTenantId(tenantId);
 | 
			
		||||
@ -127,6 +225,13 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        return customerService.saveCustomer(customer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void checkImportedCustomerData(Customer initialCustomer, Customer importedCustomer) {
 | 
			
		||||
        assertThat(importedCustomer.getTitle()).isEqualTo(initialCustomer.getTitle());
 | 
			
		||||
        assertThat(importedCustomer.getCountry()).isEqualTo(initialCustomer.getCountry());
 | 
			
		||||
        assertThat(importedCustomer.getAddress()).isEqualTo(initialCustomer.getAddress());
 | 
			
		||||
        assertThat(importedCustomer.getEmail()).isEqualTo(initialCustomer.getEmail());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected Dashboard createDashboard(TenantId tenantId, CustomerId customerId, String name) {
 | 
			
		||||
        Dashboard dashboard = new Dashboard();
 | 
			
		||||
        dashboard.setTenantId(tenantId);
 | 
			
		||||
@ -142,6 +247,16 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        return dashboard;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void checkImportedDashboardData(Dashboard initialDashboard, Dashboard importedDashboard) {
 | 
			
		||||
        assertThat(importedDashboard.getTitle()).isEqualTo(initialDashboard.getTitle());
 | 
			
		||||
        assertThat(importedDashboard.getConfiguration()).isEqualTo(initialDashboard.getConfiguration());
 | 
			
		||||
        assertThat(importedDashboard.getImage()).isEqualTo(initialDashboard.getImage());
 | 
			
		||||
        assertThat(importedDashboard.isMobileHide()).isEqualTo(initialDashboard.isMobileHide());
 | 
			
		||||
        if (initialDashboard.getAssignedCustomers() != null) {
 | 
			
		||||
            assertThat(importedDashboard.getAssignedCustomers()).containsAll(initialDashboard.getAssignedCustomers());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected RuleChain createRuleChain(TenantId tenantId, String name) {
 | 
			
		||||
        RuleChain ruleChain = new RuleChain();
 | 
			
		||||
        ruleChain.setTenantId(tenantId);
 | 
			
		||||
@ -178,6 +293,50 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        return ruleChainService.findRuleChainById(tenantId, ruleChain.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void checkImportedRuleChainData(RuleChain initialRuleChain, RuleChainMetaData initialMetaData, RuleChain importedRuleChain, RuleChainMetaData importedMetaData) {
 | 
			
		||||
        assertThat(importedRuleChain.getType()).isEqualTo(initialRuleChain.getType());
 | 
			
		||||
        assertThat(importedRuleChain.getName()).isEqualTo(initialRuleChain.getName());
 | 
			
		||||
        assertThat(importedRuleChain.isDebugMode()).isEqualTo(initialRuleChain.isDebugMode());
 | 
			
		||||
        assertThat(importedRuleChain.getConfiguration()).isEqualTo(initialRuleChain.getConfiguration());
 | 
			
		||||
 | 
			
		||||
        assertThat(importedMetaData.getConnections()).isEqualTo(initialMetaData.getConnections());
 | 
			
		||||
        assertThat(importedMetaData.getFirstNodeIndex()).isEqualTo(initialMetaData.getFirstNodeIndex());
 | 
			
		||||
        for (int i = 0; i < initialMetaData.getNodes().size(); i++) {
 | 
			
		||||
            RuleNode initialNode = initialMetaData.getNodes().get(i);
 | 
			
		||||
            RuleNode importedNode = importedMetaData.getNodes().get(i);
 | 
			
		||||
            assertThat(importedNode.getRuleChainId()).isEqualTo(importedRuleChain.getId());
 | 
			
		||||
            assertThat(importedNode.getName()).isEqualTo(initialNode.getName());
 | 
			
		||||
            assertThat(importedNode.getType()).isEqualTo(initialNode.getType());
 | 
			
		||||
            assertThat(importedNode.getConfiguration()).isEqualTo(initialNode.getConfiguration());
 | 
			
		||||
            assertThat(importedNode.getAdditionalInfo()).isEqualTo(initialNode.getAdditionalInfo());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected EntityRelation createRelation(EntityId from, EntityId to) {
 | 
			
		||||
        EntityRelation relation = new EntityRelation();
 | 
			
		||||
        relation.setFrom(from);
 | 
			
		||||
        relation.setTo(to);
 | 
			
		||||
        relation.setType(EntityRelation.MANAGES_TYPE);
 | 
			
		||||
        relation.setAdditionalInfo(JacksonUtil.newObjectNode().set("a", new TextNode("b")));
 | 
			
		||||
        relation.setTypeGroup(RelationTypeGroup.COMMON);
 | 
			
		||||
        relationService.saveRelation(TenantId.SYS_TENANT_ID, relation);
 | 
			
		||||
        return relation;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected <E extends ExportableEntity<?> & HasTenantId> void checkImportedEntity(TenantId tenantId1, E initialEntity, TenantId tenantId2, E importedEntity) {
 | 
			
		||||
        assertThat(initialEntity.getTenantId()).isEqualTo(tenantId1);
 | 
			
		||||
        assertThat(importedEntity.getTenantId()).isEqualTo(tenantId2);
 | 
			
		||||
 | 
			
		||||
        assertThat(importedEntity.getExternalId()).isEqualTo(initialEntity.getId());
 | 
			
		||||
 | 
			
		||||
        boolean sameTenant = tenantId1.equals(tenantId2);
 | 
			
		||||
        if (!sameTenant) {
 | 
			
		||||
            assertThat(importedEntity.getId()).isNotEqualTo(initialEntity.getId());
 | 
			
		||||
        } else {
 | 
			
		||||
            assertThat(importedEntity.getId()).isEqualTo(initialEntity.getId());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected <E extends ExportableEntity<I>, I extends EntityId> EntityExportData<E> exportSingleEntity(I entityId) throws Exception {
 | 
			
		||||
        SingleEntityExportRequest exportRequest = new SingleEntityExportRequest();
 | 
			
		||||
@ -186,33 +345,30 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        return (EntityExportData<E>) exportEntities(exportRequest).get(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<EntityExportData<ExportableEntity<EntityId>>> exportEntities(ExportRequest exportRequest) throws Exception {
 | 
			
		||||
        return getResponse(doPost("/api/entities/export", exportRequest), new TypeReference<List<EntityExportData<ExportableEntity<EntityId>>>>() {});
 | 
			
		||||
    protected List<EntityExportData<?>> exportEntities(ExportRequest exportRequest) throws Exception {
 | 
			
		||||
        return getResponse(doPost("/api/entities/export", exportRequest), new TypeReference<List<EntityExportData<?>>>() {});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<EntityExportData<ExportableEntity<EntityId>>> exportEntities(List<ExportRequest> exportRequests) throws Exception {
 | 
			
		||||
        return getResponse(doPost("/api/entities/export?multiple", exportRequests), new TypeReference<List<EntityExportData<ExportableEntity<EntityId>>>>() {});
 | 
			
		||||
    protected List<EntityExportData<?>> exportEntities(List<ExportRequest> exportRequests) throws Exception {
 | 
			
		||||
        return getResponse(doPost("/api/entities/export?multiple", exportRequests), new TypeReference<List<EntityExportData<?>>>() {});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected <E extends ExportableEntity<I>, I extends EntityId> EntityImportResult<E> importEntity(EntityExportData<E> exportData) throws Exception {
 | 
			
		||||
        return (EntityImportResult<E>) importEntities(List.of((EntityExportData<ExportableEntity<EntityId>>)exportData)).get(0);
 | 
			
		||||
        return (EntityImportResult<E>) importEntities(List.of((EntityExportData<ExportableEntity<EntityId>>) exportData)).get(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<EntityImportResult<ExportableEntity<EntityId>>> importEntities(List<EntityExportData<ExportableEntity<EntityId>>> exportDataList) throws Exception {
 | 
			
		||||
    protected List<EntityImportResult<?>> importEntities(List<EntityExportData<?>> exportDataList) throws Exception {
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .updateReferencesToOtherEntities(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        importRequest.setExportDataList(exportDataList);
 | 
			
		||||
        return getResponse(doPost("/api/entities/import", importRequest), new TypeReference<List<EntityImportResult<ExportableEntity<EntityId>>>>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public Type getType() {
 | 
			
		||||
                return mapper.getTypeFactory().constructCollectionType(List.class,
 | 
			
		||||
                        mapper.getTypeFactory().constructParametricType(EntityImportResult.class,
 | 
			
		||||
                                exportDataList.get(0).getEntity().getClass()));
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        return importEntities(importRequest);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<EntityImportResult<?>> importEntities(ImportRequest importRequest) throws Exception {
 | 
			
		||||
        return getResponse(doPost("/api/entities/import", importRequest), new TypeReference<List<EntityImportResult<?>>>() {});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected <T> T getResponse(ResultActions resultActions, TypeReference<T> typeReference) throws Exception {
 | 
			
		||||
@ -223,4 +379,13 @@ public abstract class BaseEntitiesExportImportControllerTest extends AbstractCon
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    protected void logInAsTenantAdmin1() throws Exception {
 | 
			
		||||
        login(tenantAdmin1.getEmail(), "12345678");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void logInAsTenantAdmin2() throws Exception {
 | 
			
		||||
        login(tenantAdmin2.getEmail(), "12345678");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -15,86 +15,81 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.controller.sql;
 | 
			
		||||
 | 
			
		||||
import org.junit.After;
 | 
			
		||||
import org.junit.Before;
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
			
		||||
import com.fasterxml.jackson.databind.node.TextNode;
 | 
			
		||||
import com.google.common.collect.Streams;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.test.mock.mockito.SpyBean;
 | 
			
		||||
import org.testcontainers.shaded.org.apache.commons.lang.RandomStringUtils;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.server.cluster.TbClusterService;
 | 
			
		||||
import org.thingsboard.server.common.data.Customer;
 | 
			
		||||
import org.thingsboard.server.common.data.Dashboard;
 | 
			
		||||
import org.thingsboard.server.common.data.Device;
 | 
			
		||||
import org.thingsboard.server.common.data.DeviceProfile;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
import org.thingsboard.server.common.data.ExportableEntity;
 | 
			
		||||
import org.thingsboard.server.common.data.HasTenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.Tenant;
 | 
			
		||||
import org.thingsboard.server.common.data.User;
 | 
			
		||||
import org.thingsboard.server.common.data.OtaPackage;
 | 
			
		||||
import org.thingsboard.server.common.data.asset.Asset;
 | 
			
		||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
			
		||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
 | 
			
		||||
import org.thingsboard.server.common.data.id.AssetId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.ota.OtaPackageType;
 | 
			
		||||
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
 | 
			
		||||
import org.thingsboard.server.common.data.query.EntityListFilter;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.EntityRelation;
 | 
			
		||||
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
 | 
			
		||||
import org.thingsboard.server.common.data.rule.RuleNode;
 | 
			
		||||
import org.thingsboard.server.common.data.security.Authority;
 | 
			
		||||
import org.thingsboard.server.common.data.security.DeviceCredentials;
 | 
			
		||||
import org.thingsboard.server.controller.BaseEntitiesExportImportControllerTest;
 | 
			
		||||
import org.thingsboard.server.dao.device.DeviceCredentialsService;
 | 
			
		||||
import org.thingsboard.server.dao.service.DaoSqlTest;
 | 
			
		||||
import org.thingsboard.server.dao.tenant.TenantService;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.ExportableEntitiesService;
 | 
			
		||||
import org.thingsboard.server.service.action.EntityActionService;
 | 
			
		||||
import org.thingsboard.server.service.ota.OtaPackageStateService;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.DeviceExportData;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.RuleChainExportData;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.CustomEntityFilterExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityExportSettings;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityListExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.EntityTypeExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.ExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.exporting.data.request.SingleEntityExportRequest;
 | 
			
		||||
import org.thingsboard.server.service.sync.importing.data.EntityImportResult;
 | 
			
		||||
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
 | 
			
		||||
import org.thingsboard.server.service.sync.importing.data.request.ImportRequest;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.any;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.isNull;
 | 
			
		||||
import static org.mockito.Mockito.verify;
 | 
			
		||||
 | 
			
		||||
@DaoSqlTest
 | 
			
		||||
public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImportControllerTest {
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private TenantService tenantService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private DeviceCredentialsService deviceCredentialsService;
 | 
			
		||||
    @Autowired
 | 
			
		||||
    private ExportableEntitiesService exportableEntitiesService;
 | 
			
		||||
 | 
			
		||||
    private TenantId tenantId1;
 | 
			
		||||
    private User tenantAdmin1;
 | 
			
		||||
 | 
			
		||||
    private TenantId tenantId2;
 | 
			
		||||
    private User tenantAdmin2;
 | 
			
		||||
 | 
			
		||||
    @Before
 | 
			
		||||
    public void beforeEach() throws Exception {
 | 
			
		||||
        loginSysAdmin();
 | 
			
		||||
        Tenant tenant1 = new Tenant();
 | 
			
		||||
        tenant1.setTitle("Tenant 1");
 | 
			
		||||
        tenant1.setEmail("tenant1@thingsboard.org");
 | 
			
		||||
        this.tenantId1 = tenantService.saveTenant(tenant1).getId();
 | 
			
		||||
        User tenantAdmin1 = new User();
 | 
			
		||||
        tenantAdmin1.setTenantId(tenantId1);
 | 
			
		||||
        tenantAdmin1.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        tenantAdmin1.setEmail("tenant1-admin@thingsboard.org");
 | 
			
		||||
        this.tenantAdmin1 = createUser(tenantAdmin1, "12345678");
 | 
			
		||||
        Tenant tenant2 = new Tenant();
 | 
			
		||||
        tenant2.setTitle("Tenant 2");
 | 
			
		||||
        tenant2.setEmail("tenant2@thingsboard.org");
 | 
			
		||||
        this.tenantId2 = tenantService.saveTenant(tenant2).getId();
 | 
			
		||||
        User tenantAdmin2 = new User();
 | 
			
		||||
        tenantAdmin2.setTenantId(tenantId2);
 | 
			
		||||
        tenantAdmin2.setAuthority(Authority.TENANT_ADMIN);
 | 
			
		||||
        tenantAdmin2.setEmail("tenant2-admin@thingsboard.org");
 | 
			
		||||
        this.tenantAdmin2 = createUser(tenantAdmin2, "12345678");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @After
 | 
			
		||||
    public void afterEach() {
 | 
			
		||||
        tenantService.deleteTenant(tenantId1);
 | 
			
		||||
        tenantService.deleteTenant(tenantId2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SpyBean
 | 
			
		||||
    private EntityActionService entityActionService;
 | 
			
		||||
    @SpyBean
 | 
			
		||||
    private TbClusterService clusterService;
 | 
			
		||||
    @SpyBean
 | 
			
		||||
    private OtaPackageStateService otaPackageStateService;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleAsset_betweenTenants() throws Exception {
 | 
			
		||||
    public void testExportImportAsset_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Asset asset = createAsset(tenantId1, null, "AB", "Asset of tenant 1");
 | 
			
		||||
        EntityExportData<Asset> exportData = exportSingleEntity(asset.getId());
 | 
			
		||||
@ -103,40 +98,24 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        EntityImportResult<Asset> importResult = importEntity(exportData);
 | 
			
		||||
 | 
			
		||||
        checkImportedEntity(tenantId1, asset, tenantId2, importResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, asset, tenantId2, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedAssetData(asset, importResult.getSavedEntity());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleAsset_sameTenant() throws Exception {
 | 
			
		||||
    public void testExportImportAsset_sameTenant() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Asset asset = createAsset(tenantId1, null, "AB", "Asset v1.0");
 | 
			
		||||
        EntityExportData<Asset> exportData = exportSingleEntity(asset.getId());
 | 
			
		||||
 | 
			
		||||
        EntityImportResult<Asset> importResult = importEntity(exportData);
 | 
			
		||||
 | 
			
		||||
        checkImportedEntity(tenantId1, asset, tenantId1, importResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, asset, tenantId1, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedAssetData(asset, importResult.getSavedEntity());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportAsset_withCustomer_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "My customer");
 | 
			
		||||
        Asset asset = createAsset(tenantId1, customer.getId(), "AB", "My asset");
 | 
			
		||||
 | 
			
		||||
        EntityExportData<Customer> customerExportData = exportSingleEntity(customer.getId());
 | 
			
		||||
        EntityExportData<Asset> assetExportData = exportSingleEntity(asset.getId());
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        Customer importedCustomer = importEntity(customerExportData).getSavedEntity();
 | 
			
		||||
        Asset importedAsset = importEntity(assetExportData).getSavedEntity();
 | 
			
		||||
 | 
			
		||||
        assertThat(importedAsset.getCustomerId()).isEqualTo(importedCustomer.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportAsset_withCustomer_sameTenant() throws Exception {
 | 
			
		||||
    public void testExportImportAsset_sameTenant_withCustomer() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "My customer");
 | 
			
		||||
        Asset asset = createAsset(tenantId1, customer.getId(), "AB", "My asset");
 | 
			
		||||
@ -146,16 +125,9 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
        assertThat(importedAsset.getCustomerId()).isEqualTo(asset.getCustomerId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkImportedAssetData(Asset initialAsset, Asset importedAsset) {
 | 
			
		||||
        assertThat(importedAsset.getName()).isEqualTo(initialAsset.getName());
 | 
			
		||||
        assertThat(importedAsset.getType()).isEqualTo(initialAsset.getType());
 | 
			
		||||
        assertThat(importedAsset.getLabel()).isEqualTo(initialAsset.getLabel());
 | 
			
		||||
        assertThat(importedAsset.getAdditionalInfo()).isEqualTo(initialAsset.getAdditionalInfo());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleCustomer_betweenTenants() throws Exception {
 | 
			
		||||
    public void testExportImportCustomer_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Customer customer = createCustomer(tenantAdmin1.getTenantId(), "Customer of tenant 1");
 | 
			
		||||
        EntityExportData<Customer> exportData = exportSingleEntity(customer.getId());
 | 
			
		||||
@ -164,34 +136,27 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        EntityImportResult<Customer> importResult = importEntity(exportData);
 | 
			
		||||
 | 
			
		||||
        checkImportedEntity(tenantId1, customer, tenantId2, importResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, customer, tenantId2, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedCustomerData(customer, importResult.getSavedEntity());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleCustomer_sameTenant() throws Exception {
 | 
			
		||||
    public void testExportImportCustomer_sameTenant() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Customer customer = createCustomer(tenantAdmin1.getTenantId(), "Customer v1.0");
 | 
			
		||||
        EntityExportData<Customer> exportData = exportSingleEntity(customer.getId());
 | 
			
		||||
 | 
			
		||||
        EntityImportResult<Customer> importResult = importEntity(exportData);
 | 
			
		||||
 | 
			
		||||
        checkImportedEntity(tenantId1, customer, tenantId1, importResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, customer, tenantId1, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedCustomerData(customer, importResult.getSavedEntity());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkImportedCustomerData(Customer initialCustomer, Customer importedCustomer) {
 | 
			
		||||
        assertThat(importedCustomer.getTitle()).isEqualTo(initialCustomer.getTitle());
 | 
			
		||||
        assertThat(importedCustomer.getCountry()).isEqualTo(initialCustomer.getCountry());
 | 
			
		||||
        assertThat(importedCustomer.getAddress()).isEqualTo(initialCustomer.getAddress());
 | 
			
		||||
        assertThat(importedCustomer.getEmail()).isEqualTo(initialCustomer.getEmail());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportDeviceWithProfile_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        DeviceProfile deviceProfile = createDeviceProfile(tenantId1, "Device profile of tenant 1");
 | 
			
		||||
        DeviceProfile deviceProfile = createDeviceProfile(tenantId1, null, null, "Device profile of tenant 1");
 | 
			
		||||
        Device device = createDevice(tenantId1, null, deviceProfile.getId(), "Device of tenant 1");
 | 
			
		||||
        DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId1, device.getId());
 | 
			
		||||
 | 
			
		||||
@ -206,13 +171,13 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        EntityImportResult<DeviceProfile> profileImportResult = importEntity(profileExportData);
 | 
			
		||||
        checkImportedEntity(tenantId1, deviceProfile, tenantId2, profileImportResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, deviceProfile, tenantId2, profileImportResult.getSavedEntity());
 | 
			
		||||
        checkImportedDeviceProfileData(deviceProfile, profileImportResult.getSavedEntity());
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        EntityImportResult<Device> deviceImportResult = importEntity(deviceExportData);
 | 
			
		||||
        Device importedDevice = deviceImportResult.getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, device, tenantId2, deviceImportResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, device, tenantId2, deviceImportResult.getSavedEntity());
 | 
			
		||||
        checkImportedDeviceData(device, importedDevice);
 | 
			
		||||
 | 
			
		||||
        assertThat(importedDevice.getDeviceProfileId()).isEqualTo(profileImportResult.getSavedEntity().getId());
 | 
			
		||||
@ -227,8 +192,14 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportDevice_sameTenant() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        DeviceProfile deviceProfile = createDeviceProfile(tenantId1, "Device profile v1.0");
 | 
			
		||||
        DeviceProfile deviceProfile = createDeviceProfile(tenantId1, null, null, "Device profile v1.0");
 | 
			
		||||
        OtaPackage firmware = createOtaPackage(tenantId1, deviceProfile.getId(), OtaPackageType.FIRMWARE);
 | 
			
		||||
        OtaPackage software = createOtaPackage(tenantId1, deviceProfile.getId(), OtaPackageType.SOFTWARE);
 | 
			
		||||
        Device device = createDevice(tenantId1, null, deviceProfile.getId(), "Device v1.0");
 | 
			
		||||
        device.setFirmwareId(firmware.getId());
 | 
			
		||||
        device.setSoftwareId(software.getId());
 | 
			
		||||
        device = deviceService.saveDevice(device);
 | 
			
		||||
 | 
			
		||||
        DeviceCredentials credentials = deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId1, device.getId());
 | 
			
		||||
 | 
			
		||||
        EntityExportData<Device> deviceExportData = exportSingleEntity(device.getId());
 | 
			
		||||
@ -236,29 +207,119 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
        EntityImportResult<Device> importResult = importEntity(deviceExportData);
 | 
			
		||||
        Device importedDevice = importResult.getSavedEntity();
 | 
			
		||||
 | 
			
		||||
        checkImportedEntity(tenantId1, device, tenantId1, importResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, device, tenantId1, importResult.getSavedEntity());
 | 
			
		||||
        assertThat(importedDevice.getDeviceProfileId()).isEqualTo(device.getDeviceProfileId());
 | 
			
		||||
        assertThat(deviceCredentialsService.findDeviceCredentialsByDeviceId(tenantId1, device.getId())).isEqualTo(credentials);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkImportedDeviceProfileData(DeviceProfile initialProfile, DeviceProfile importedProfile) {
 | 
			
		||||
        assertThat(initialProfile.getName()).isEqualTo(importedProfile.getName());
 | 
			
		||||
        assertThat(initialProfile.getType()).isEqualTo(importedProfile.getType());
 | 
			
		||||
        assertThat(initialProfile.getTransportType()).isEqualTo(importedProfile.getTransportType());
 | 
			
		||||
        assertThat(initialProfile.getProfileData()).isEqualTo(importedProfile.getProfileData());
 | 
			
		||||
        assertThat(initialProfile.getDescription()).isEqualTo(importedProfile.getDescription());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkImportedDeviceData(Device initialDevice, Device importedDevice) {
 | 
			
		||||
        assertThat(importedDevice.getName()).isEqualTo(initialDevice.getName());
 | 
			
		||||
        assertThat(importedDevice.getType()).isEqualTo(initialDevice.getType());
 | 
			
		||||
        assertThat(importedDevice.getDeviceData()).isEqualTo(initialDevice.getDeviceData());
 | 
			
		||||
        assertThat(importedDevice.getLabel()).isEqualTo(initialDevice.getLabel());
 | 
			
		||||
        assertThat(importedDevice.getFirmwareId()).isEqualTo(firmware.getId());
 | 
			
		||||
        assertThat(importedDevice.getSoftwareId()).isEqualTo(software.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleRuleChain_betweenTenants() throws Exception {
 | 
			
		||||
    public void testExportImportDashboard_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantAdmin1.getTenantId(), null, "Dashboard of tenant 1");
 | 
			
		||||
 | 
			
		||||
        EntityExportData<Dashboard> exportData = exportSingleEntity(dashboard.getId());
 | 
			
		||||
        assertThat(exportData.getEntity()).isEqualTo(dashboard);
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        EntityImportResult<Dashboard> importResult = importEntity(exportData);
 | 
			
		||||
        checkImportedEntity(tenantId1, dashboard, tenantId2, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedDashboardData(dashboard, importResult.getSavedEntity());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportDashboard_sameTenant() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantAdmin1.getTenantId(), null, "Dashboard v1.0");
 | 
			
		||||
 | 
			
		||||
        EntityExportData<Dashboard> exportData = exportSingleEntity(dashboard.getId());
 | 
			
		||||
 | 
			
		||||
        EntityImportResult<Dashboard> importResult = importEntity(exportData);
 | 
			
		||||
        checkImportedEntity(tenantId1, dashboard, tenantId1, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedDashboardData(dashboard, importResult.getSavedEntity());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportDashboard_betweenTenants_withCustomer_updated() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantAdmin1.getTenantId(), null, "Dashboard of tenant 1");
 | 
			
		||||
 | 
			
		||||
        EntityExportData<Dashboard> exportData = exportSingleEntity(dashboard.getId());
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        Dashboard importedDashboard = (Dashboard) importEntities(List.of(exportData)).get(0).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, dashboard, tenantId2, importedDashboard);
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "Customer 1");
 | 
			
		||||
        EntityExportData<Customer> customerExportData = exportSingleEntity(customer.getId());
 | 
			
		||||
        dashboardService.assignDashboardToCustomer(tenantId1, dashboard.getId(), customer.getId());
 | 
			
		||||
        exportData = exportSingleEntity(dashboard.getId());
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        Customer importedCustomer = (Customer) importEntities(List.of(customerExportData)).get(0).getSavedEntity();
 | 
			
		||||
        importedDashboard = (Dashboard) importEntities(List.of(exportData)).get(0).getSavedEntity();
 | 
			
		||||
        assertThat(importedDashboard.getAssignedCustomers()).hasOnlyOneElementSatisfying(customerInfo -> {
 | 
			
		||||
            assertThat(customerInfo.getCustomerId()).isEqualTo(importedCustomer.getId());
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportDashboard_betweenTenants_withEntityAliases() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Asset asset1 = createAsset(tenantId1, null, "A", "Asset 1");
 | 
			
		||||
        Asset asset2 = createAsset(tenantId1, null, "A", "Asset 2");
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantId1, null, "Dashboard 1");
 | 
			
		||||
 | 
			
		||||
        String entityAliases = "{\n" +
 | 
			
		||||
                "\t\"23c4185d-1497-9457-30b2-6d91e69a5b2c\": {\n" +
 | 
			
		||||
                "\t\t\"alias\": \"assets\",\n" +
 | 
			
		||||
                "\t\t\"filter\": {\n" +
 | 
			
		||||
                "\t\t\t\"entityList\": [\n" +
 | 
			
		||||
                "\t\t\t\t\"" + asset1.getId().toString() + "\",\n" +
 | 
			
		||||
                "\t\t\t\t\"" + asset2.getId().toString() + "\"\n" +
 | 
			
		||||
                "\t\t\t],\n" +
 | 
			
		||||
                "\t\t\t\"entityType\": \"ASSET\",\n" +
 | 
			
		||||
                "\t\t\t\"resolveMultiple\": true,\n" +
 | 
			
		||||
                "\t\t\t\"type\": \"entityList\"\n" +
 | 
			
		||||
                "\t\t},\n" +
 | 
			
		||||
                "\t\t\"id\": \"23c4185d-1497-9457-30b2-6d91e69a5b2c\"\n" +
 | 
			
		||||
                "\t}\n" +
 | 
			
		||||
                "}";
 | 
			
		||||
        ObjectNode dashboardConfiguration = JacksonUtil.newObjectNode();
 | 
			
		||||
        dashboardConfiguration.set("entityAliases", JacksonUtil.toJsonNode(entityAliases));
 | 
			
		||||
        dashboardConfiguration.set("description", new TextNode("hallo"));
 | 
			
		||||
        dashboard.setConfiguration(dashboardConfiguration);
 | 
			
		||||
        dashboard = dashboardService.saveDashboard(dashboard);
 | 
			
		||||
 | 
			
		||||
        EntityTypeExportRequest assetsExportRequest = new EntityTypeExportRequest();
 | 
			
		||||
        assetsExportRequest.setEntityType(EntityType.ASSET);
 | 
			
		||||
        assetsExportRequest.setPageSize(10);
 | 
			
		||||
        assetsExportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
        EntityTypeExportRequest dashboardsExportRequest = new EntityTypeExportRequest();
 | 
			
		||||
        dashboardsExportRequest.setEntityType(EntityType.DASHBOARD);
 | 
			
		||||
        dashboardsExportRequest.setPageSize(10);
 | 
			
		||||
        dashboardsExportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(List.of(assetsExportRequest, dashboardsExportRequest));
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        Map<EntityType, List<EntityImportResult<?>>> importResults = importEntities(exportDataList).stream().collect(Collectors.groupingBy(EntityImportResult::getEntityType));
 | 
			
		||||
        Asset importedAsset1 = (Asset) importResults.get(EntityType.ASSET).get(0).getSavedEntity();
 | 
			
		||||
        Asset importedAsset2 = (Asset) importResults.get(EntityType.ASSET).get(1).getSavedEntity();
 | 
			
		||||
        Dashboard importedDashboard = (Dashboard) importResults.get(EntityType.DASHBOARD).get(0).getSavedEntity();
 | 
			
		||||
 | 
			
		||||
        Set<String> entityAliasEntitiesIds = Streams.stream(importedDashboard.getConfiguration()
 | 
			
		||||
                .get("entityAliases").elements().next().get("filter").get("entityList").elements())
 | 
			
		||||
                .map(JsonNode::asText).collect(Collectors.toSet());
 | 
			
		||||
        assertThat(entityAliasEntitiesIds).doesNotContain(asset1.getId().toString(), asset2.getId().toString());
 | 
			
		||||
        assertThat(entityAliasEntitiesIds).contains(importedAsset1.getId().toString(), importedAsset2.getId().toString());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportRuleChain_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        RuleChain ruleChain = createRuleChain(tenantId1, "Rule chain of tenant 1");
 | 
			
		||||
        RuleChainMetaData metaData = ruleChainService.loadRuleChainMetaData(tenantId1, ruleChain.getId());
 | 
			
		||||
@ -272,12 +333,12 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
        RuleChain importedRuleChain = importResult.getSavedEntity();
 | 
			
		||||
        RuleChainMetaData importedMetaData = ruleChainService.loadRuleChainMetaData(tenantId2, importedRuleChain.getId());
 | 
			
		||||
 | 
			
		||||
        checkImportedEntity(tenantId1, ruleChain, tenantId2, importResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, ruleChain, tenantId2, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedRuleChainData(ruleChain, metaData, importedRuleChain, importedMetaData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleRuleChain_sameTenant() throws Exception {
 | 
			
		||||
    public void testExportImportRuleChain_sameTenant() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        RuleChain ruleChain = createRuleChain(tenantId1, "Rule chain v1.0");
 | 
			
		||||
        RuleChainMetaData metaData = ruleChainService.loadRuleChainMetaData(tenantId1, ruleChain.getId());
 | 
			
		||||
@ -288,91 +349,439 @@ public class EntitiesExportImportControllerSqlTest extends BaseEntitiesExportImp
 | 
			
		||||
        RuleChain importedRuleChain = importResult.getSavedEntity();
 | 
			
		||||
        RuleChainMetaData importedMetaData = ruleChainService.loadRuleChainMetaData(tenantId1, importedRuleChain.getId());
 | 
			
		||||
 | 
			
		||||
        checkImportedEntity(tenantId1, ruleChain, tenantId1, importResult);
 | 
			
		||||
        checkImportedEntity(tenantId1, ruleChain, tenantId1, importResult.getSavedEntity());
 | 
			
		||||
        checkImportedRuleChainData(ruleChain, metaData, importedRuleChain, importedMetaData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkImportedRuleChainData(RuleChain initialRuleChain, RuleChainMetaData initialMetaData, RuleChain importedRuleChain, RuleChainMetaData importedMetaData) {
 | 
			
		||||
        assertThat(importedRuleChain.getType()).isEqualTo(initialRuleChain.getType());
 | 
			
		||||
        assertThat(importedRuleChain.getName()).isEqualTo(initialRuleChain.getName());
 | 
			
		||||
        assertThat(importedRuleChain.isDebugMode()).isEqualTo(initialRuleChain.isDebugMode());
 | 
			
		||||
        assertThat(importedRuleChain.getConfiguration()).isEqualTo(initialRuleChain.getConfiguration());
 | 
			
		||||
 | 
			
		||||
        assertThat(importedMetaData.getConnections()).isEqualTo(initialMetaData.getConnections());
 | 
			
		||||
        assertThat(importedMetaData.getFirstNodeIndex()).isEqualTo(initialMetaData.getFirstNodeIndex());
 | 
			
		||||
        for (int i = 0; i < initialMetaData.getNodes().size(); i++) {
 | 
			
		||||
            RuleNode initialNode = initialMetaData.getNodes().get(i);
 | 
			
		||||
            RuleNode importedNode = importedMetaData.getNodes().get(i);
 | 
			
		||||
            assertThat(importedNode.getRuleChainId()).isEqualTo(importedRuleChain.getId());
 | 
			
		||||
            assertThat(importedNode.getName()).isEqualTo(initialNode.getName());
 | 
			
		||||
            assertThat(importedNode.getType()).isEqualTo(initialNode.getType());
 | 
			
		||||
            assertThat(importedNode.getConfiguration()).isEqualTo(initialNode.getConfiguration());
 | 
			
		||||
            assertThat(importedNode.getAdditionalInfo()).isEqualTo(initialNode.getAdditionalInfo());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleDashboard_betweenTenants() throws Exception {
 | 
			
		||||
    public void testExportImportBatch_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantAdmin1.getTenantId(), null, "Dashboard of tenant 1");
 | 
			
		||||
 | 
			
		||||
        EntityExportData<Dashboard> exportData = exportSingleEntity(dashboard.getId());
 | 
			
		||||
        assertThat(exportData.getEntity()).isEqualTo(dashboard);
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "Customer 1");
 | 
			
		||||
        Asset asset = createAsset(tenantId1, customer.getId(), "A", "Customer 1 - Asset 1");
 | 
			
		||||
        RuleChain ruleChain = createRuleChain(tenantId1, "Rule chain 1");
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantId1, customer.getId(), "Customer 1 - Dashboard 1");
 | 
			
		||||
        DeviceProfile deviceProfile = createDeviceProfile(tenantId1, ruleChain.getId(), dashboard.getId(), "Device profile 1");
 | 
			
		||||
        Device device = createDevice(tenantId1, customer.getId(), deviceProfile.getId(), "Customer 1 - Device 1");
 | 
			
		||||
 | 
			
		||||
        EntityListExportRequest exportRequest = new EntityListExportRequest();
 | 
			
		||||
        exportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
        exportRequest.setEntitiesIds(List.of(customer.getId(), asset.getId(), ruleChain.getId(), deviceProfile.getId(), dashboard.getId()));
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequest);
 | 
			
		||||
        exportRequest.setEntitiesIds(List.of(device.getId()));
 | 
			
		||||
        DeviceExportData deviceExportData = (DeviceExportData) exportEntities(exportRequest).get(0);
 | 
			
		||||
        deviceExportData.getCredentials().setCredentialsId(RandomStringUtils.randomAlphanumeric(10));
 | 
			
		||||
        exportDataList.add(deviceExportData);
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        EntityImportResult<Dashboard> importResult = importEntity(exportData);
 | 
			
		||||
        checkImportedEntity(tenantId1, dashboard, tenantId2, importResult);
 | 
			
		||||
        checkImportedDashboardData(dashboard, importResult.getSavedEntity());
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .updateReferencesToOtherEntities(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        importRequest.setExportDataList(exportDataList);
 | 
			
		||||
        Map<EntityType, EntityImportResult<?>> importResults = importEntities(importRequest).stream()
 | 
			
		||||
                .collect(Collectors.toMap(EntityImportResult::getEntityType, r -> r));
 | 
			
		||||
 | 
			
		||||
        Customer importedCustomer = (Customer) importResults.get(EntityType.CUSTOMER).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, customer, tenantId2, importedCustomer);
 | 
			
		||||
 | 
			
		||||
        Asset importedAsset = (Asset) importResults.get(EntityType.ASSET).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, asset, tenantId2, importedAsset);
 | 
			
		||||
        assertThat(importedAsset.getCustomerId()).isEqualTo(importedCustomer.getId());
 | 
			
		||||
 | 
			
		||||
        RuleChain importedRuleChain = (RuleChain) importResults.get(EntityType.RULE_CHAIN).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, ruleChain, tenantId2, importedRuleChain);
 | 
			
		||||
 | 
			
		||||
        Dashboard importedDashboard = (Dashboard) importResults.get(EntityType.DASHBOARD).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, dashboard, tenantId2, importedDashboard);
 | 
			
		||||
        assertThat(importedDashboard.getAssignedCustomers()).size().isOne();
 | 
			
		||||
        assertThat(importedDashboard.getAssignedCustomers()).hasOnlyOneElementSatisfying(customerInfo -> {
 | 
			
		||||
            assertThat(customerInfo.getCustomerId()).isEqualTo(importedCustomer.getId());
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        DeviceProfile importedDeviceProfile = (DeviceProfile) importResults.get(EntityType.DEVICE_PROFILE).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, deviceProfile, tenantId2, importedDeviceProfile);
 | 
			
		||||
        assertThat(importedDeviceProfile.getDefaultRuleChainId()).isEqualTo(importedRuleChain.getId());
 | 
			
		||||
        assertThat(importedDeviceProfile.getDefaultDashboardId()).isEqualTo(importedDashboard.getId());
 | 
			
		||||
 | 
			
		||||
        Device importedDevice = (Device) importResults.get(EntityType.DEVICE).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, device, tenantId2, importedDevice);
 | 
			
		||||
        assertThat(importedDevice.getCustomerId()).isEqualTo(importedCustomer.getId());
 | 
			
		||||
        assertThat(importedDevice.getDeviceProfileId()).isEqualTo(importedDeviceProfile.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportWithInboundRelations_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
 | 
			
		||||
        Asset asset = createAsset(tenantId1, null, "A", "Asset 1");
 | 
			
		||||
        Device device = createDevice(tenantId1, null, null, "Device 1");
 | 
			
		||||
        EntityRelation relation = createRelation(asset.getId(), device.getId());
 | 
			
		||||
 | 
			
		||||
        EntityListExportRequest exportRequest = new EntityListExportRequest();
 | 
			
		||||
        exportRequest.setEntitiesIds(List.of(asset.getId(), device.getId()));
 | 
			
		||||
        exportRequest.setExportSettings(EntityExportSettings.builder()
 | 
			
		||||
                .exportInboundRelations(true)
 | 
			
		||||
                .exportOutboundRelations(false)
 | 
			
		||||
                .build());
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequest);
 | 
			
		||||
 | 
			
		||||
        EntityExportData<?> deviceExportData = exportDataList.stream().filter(exportData -> exportData.getEntityType() == EntityType.DEVICE).findFirst().orElse(null);
 | 
			
		||||
        assertThat(deviceExportData.getInboundRelations()).size().isOne();
 | 
			
		||||
        assertThat(deviceExportData.getInboundRelations().get(0)).matches(entityRelation -> {
 | 
			
		||||
            return entityRelation.getFrom().equals(asset.getId()) && entityRelation.getTo().equals(device.getId());
 | 
			
		||||
        });
 | 
			
		||||
        ((DeviceExportData) deviceExportData).getCredentials().setCredentialsId("ab");
 | 
			
		||||
        ((Device) deviceExportData.getEntity()).setDeviceProfileId(null);
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setExportDataList(exportDataList);
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .importInboundRelations(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        Map<EntityType, EntityImportResult<?>> importResults = importEntities(importRequest).stream().collect(Collectors.toMap(EntityImportResult::getEntityType, r -> r));
 | 
			
		||||
 | 
			
		||||
        Device importedDevice = (Device) importResults.get(EntityType.DEVICE).getSavedEntity();
 | 
			
		||||
        Asset importedAsset = (Asset) importResults.get(EntityType.ASSET).getSavedEntity();
 | 
			
		||||
        checkImportedEntity(tenantId1, device, tenantId2, importedDevice);
 | 
			
		||||
        checkImportedEntity(tenantId1, asset, tenantId2, importedAsset);
 | 
			
		||||
 | 
			
		||||
        List<EntityRelation> importedRelations = relationService.findByTo(TenantId.SYS_TENANT_ID, importedDevice.getId(), RelationTypeGroup.COMMON);
 | 
			
		||||
        assertThat(importedRelations).size().isOne();
 | 
			
		||||
        assertThat(importedRelations.get(0)).satisfies(importedRelation -> {
 | 
			
		||||
            assertThat(importedRelation.getFrom()).isEqualTo(importedAsset.getId());
 | 
			
		||||
            assertThat(importedRelation.getType()).isEqualTo(relation.getType());
 | 
			
		||||
            assertThat(importedRelation.getAdditionalInfo()).isEqualTo(relation.getAdditionalInfo());
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportSingleDashboard_sameTenant() throws Exception {
 | 
			
		||||
    public void testExportImportWithRelations_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantAdmin1.getTenantId(), null, "Dashboard v1.0");
 | 
			
		||||
 | 
			
		||||
        EntityExportData<Dashboard> exportData = exportSingleEntity(dashboard.getId());
 | 
			
		||||
        Asset asset = createAsset(tenantId1, null, "A", "Asset 1");
 | 
			
		||||
        Device device = createDevice(tenantId1, null, null, "Device 1");
 | 
			
		||||
        EntityRelation relation = createRelation(asset.getId(), device.getId());
 | 
			
		||||
 | 
			
		||||
        EntityImportResult<Dashboard> importResult = importEntity(exportData);
 | 
			
		||||
        checkImportedEntity(tenantId1, dashboard, tenantId1, importResult);
 | 
			
		||||
        checkImportedDashboardData(dashboard, importResult.getSavedEntity());
 | 
			
		||||
        EntityListExportRequest exportRequest = new EntityListExportRequest();
 | 
			
		||||
        exportRequest.setEntitiesIds(List.of(asset.getId(), device.getId()));
 | 
			
		||||
        exportRequest.setExportSettings(EntityExportSettings.builder()
 | 
			
		||||
                .exportInboundRelations(true)
 | 
			
		||||
                .exportOutboundRelations(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequest);
 | 
			
		||||
 | 
			
		||||
        assertThat(exportDataList).allMatch(exportData -> exportData.getInboundRelations().size() + exportData.getOutboundRelations().size() == 1);
 | 
			
		||||
 | 
			
		||||
        EntityExportData<?> deviceExportData = exportDataList.stream().filter(exportData -> exportData.getEntityType() == EntityType.DEVICE).findFirst().orElse(null);
 | 
			
		||||
        ((DeviceExportData) deviceExportData).getCredentials().setCredentialsId("ab");
 | 
			
		||||
        ((Device) deviceExportData.getEntity()).setDeviceProfileId(null);
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setExportDataList(exportDataList);
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .importInboundRelations(true)
 | 
			
		||||
                .importOutboundRelations(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        Map<EntityType, EntityImportResult<?>> importResults = importEntities(importRequest).stream().collect(Collectors.toMap(EntityImportResult::getEntityType, r -> r));
 | 
			
		||||
 | 
			
		||||
        Device importedDevice = (Device) importResults.get(EntityType.DEVICE).getSavedEntity();
 | 
			
		||||
        Asset importedAsset = (Asset) importResults.get(EntityType.ASSET).getSavedEntity();
 | 
			
		||||
 | 
			
		||||
        List<EntityRelation> importedRelations = relationService.findByTo(TenantId.SYS_TENANT_ID, importedDevice.getId(), RelationTypeGroup.COMMON);
 | 
			
		||||
        assertThat(importedRelations).size().isOne();
 | 
			
		||||
        assertThat(importedRelations.get(0)).satisfies(importedRelation -> {
 | 
			
		||||
            assertThat(importedRelation.getFrom()).isEqualTo(importedAsset.getId());
 | 
			
		||||
            assertThat(importedRelation.getType()).isEqualTo(relation.getType());
 | 
			
		||||
            assertThat(importedRelation.getAdditionalInfo()).isEqualTo(relation.getAdditionalInfo());
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void checkImportedDashboardData(Dashboard initialDashboard, Dashboard importedDashboard) {
 | 
			
		||||
        assertThat(importedDashboard.getTitle()).isEqualTo(initialDashboard.getTitle());
 | 
			
		||||
        assertThat(importedDashboard.getConfiguration()).isEqualTo(initialDashboard.getConfiguration());
 | 
			
		||||
        assertThat(importedDashboard.getImage()).isEqualTo(initialDashboard.getImage());
 | 
			
		||||
        assertThat(importedDashboard.isMobileHide()).isEqualTo(initialDashboard.isMobileHide());
 | 
			
		||||
        if (initialDashboard.getAssignedCustomers() != null) {
 | 
			
		||||
            assertThat(importedDashboard.getAssignedCustomers()).containsAll(initialDashboard.getAssignedCustomers());
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportWithRelations_sameTenant() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
 | 
			
		||||
        Asset asset = createAsset(tenantId1, null, "A", "Asset 1");
 | 
			
		||||
        Device device1 = createDevice(tenantId1, null, null, "Device 1");
 | 
			
		||||
        EntityRelation relation1 = createRelation(asset.getId(), device1.getId());
 | 
			
		||||
 | 
			
		||||
        SingleEntityExportRequest exportRequest = new SingleEntityExportRequest();
 | 
			
		||||
        exportRequest.setEntityId(asset.getId());
 | 
			
		||||
        exportRequest.setExportSettings(EntityExportSettings.builder()
 | 
			
		||||
                .exportOutboundRelations(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        EntityExportData<Asset> assetExportData = (EntityExportData<Asset>) exportEntities(exportRequest).get(0);
 | 
			
		||||
        assertThat(assetExportData.getOutboundRelations()).size().isOne();
 | 
			
		||||
 | 
			
		||||
        Device device2 = createDevice(tenantId1, null, null, "Device 2");
 | 
			
		||||
        EntityRelation relation2 = createRelation(asset.getId(), device2.getId());
 | 
			
		||||
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setExportDataList(List.of(assetExportData));
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .importOutboundRelations(true)
 | 
			
		||||
                .build());
 | 
			
		||||
 | 
			
		||||
        importEntities(importRequest);
 | 
			
		||||
 | 
			
		||||
        List<EntityRelation> relations = relationService.findByFrom(TenantId.SYS_TENANT_ID, asset.getId(), RelationTypeGroup.COMMON);
 | 
			
		||||
        assertThat(relations).contains(relation1, relation2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void textExportImportWithRelations_sameTenant_removeExisting() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
 | 
			
		||||
        Asset asset1 = createAsset(tenantId1, null, "A", "Asset 1");
 | 
			
		||||
        Device device = createDevice(tenantId1, null, null, "Device 1");
 | 
			
		||||
        EntityRelation relation1 = createRelation(asset1.getId(), device.getId());
 | 
			
		||||
 | 
			
		||||
        SingleEntityExportRequest exportRequest = new SingleEntityExportRequest();
 | 
			
		||||
        exportRequest.setEntityId(device.getId());
 | 
			
		||||
        exportRequest.setExportSettings(EntityExportSettings.builder()
 | 
			
		||||
                .exportInboundRelations(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        EntityExportData<?> deviceExportData = exportEntities(exportRequest).get(0);
 | 
			
		||||
        assertThat(deviceExportData.getInboundRelations()).size().isOne();
 | 
			
		||||
 | 
			
		||||
        Asset asset2 = createAsset(tenantId1, null, "A", "Asset 2");
 | 
			
		||||
        EntityRelation relation2 = createRelation(asset2.getId(), device.getId());
 | 
			
		||||
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setExportDataList(List.of(deviceExportData));
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .importInboundRelations(true)
 | 
			
		||||
                .removeExistingRelations(true)
 | 
			
		||||
                .build());
 | 
			
		||||
 | 
			
		||||
        importEntities(importRequest);
 | 
			
		||||
 | 
			
		||||
        List<EntityRelation> relations = relationService.findByTo(TenantId.SYS_TENANT_ID, device.getId(), RelationTypeGroup.COMMON);
 | 
			
		||||
        assertThat(relations).contains(relation1);
 | 
			
		||||
        assertThat(relations).doesNotContain(relation2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportDeviceProfile_betweenTenants_findExistingByName() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        DeviceProfile defaultDeviceProfile = deviceProfileService.findDefaultDeviceProfile(tenantId1);
 | 
			
		||||
 | 
			
		||||
        EntityListExportRequest exportRequest = new EntityListExportRequest();
 | 
			
		||||
        exportRequest.setEntitiesIds(List.of(defaultDeviceProfile.getId()));
 | 
			
		||||
        exportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequest);
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setExportDataList(exportDataList);
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .findExistingByName(false)
 | 
			
		||||
                .updateReferencesToOtherEntities(true)
 | 
			
		||||
                .build());
 | 
			
		||||
        assertThatThrownBy(() -> {
 | 
			
		||||
            importEntities(importRequest);
 | 
			
		||||
        }).hasMessageContaining("default device profile is present");
 | 
			
		||||
 | 
			
		||||
        importRequest.getImportSettings().setFindExistingByName(true);
 | 
			
		||||
        importEntities(importRequest);
 | 
			
		||||
        checkImportedEntity(tenantId1, defaultDeviceProfile, tenantId2, deviceProfileService.findDefaultDeviceProfile(tenantId2));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportDashboard_betweenTenants_doNotUpdateReferencesToOtherEntities() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "Customer 1");
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantId1, customer.getId(), "Dashboard 1");
 | 
			
		||||
 | 
			
		||||
        EntityListExportRequest exportRequest = new EntityListExportRequest();
 | 
			
		||||
        exportRequest.setEntitiesIds(List.of(customer.getId(), dashboard.getId()));
 | 
			
		||||
        exportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequest);
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        Map<EntityType, EntityImportResult<?>> importResults = importEntities(exportDataList).stream().collect(Collectors.toMap(EntityImportResult::getEntityType, r -> r));
 | 
			
		||||
 | 
			
		||||
        Customer importedCustomer = (Customer) importResults.get(EntityType.CUSTOMER).getSavedEntity();
 | 
			
		||||
        Dashboard importedDashboard = (Dashboard) importResults.get(EntityType.DASHBOARD).getSavedEntity();
 | 
			
		||||
        assertThat(importedDashboard.getAssignedCustomers()).hasOnlyOneElementSatisfying(customerInfo -> {
 | 
			
		||||
            assertThat(customerInfo.getCustomerId()).isEqualTo(importedCustomer.getId());
 | 
			
		||||
        });
 | 
			
		||||
        assertThat(importedDashboard.getConfiguration()).isEqualTo(dashboard.getConfiguration());
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        dashboard.setConfiguration(JacksonUtil.newObjectNode().set("aaa", new TextNode("bbb")));
 | 
			
		||||
        dashboard = dashboardService.saveDashboard(dashboard);
 | 
			
		||||
        dashboard = dashboardService.unassignDashboardFromCustomer(tenantId1, dashboard.getId(), customer.getId());
 | 
			
		||||
        EntityExportData<Dashboard> updatedDashboardExportData = exportSingleEntity(dashboard.getId());
 | 
			
		||||
        assertThat(updatedDashboardExportData.getEntity().getAssignedCustomers()).isNullOrEmpty();
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
        ImportRequest importRequest = new ImportRequest();
 | 
			
		||||
        importRequest.setExportDataList(List.of(updatedDashboardExportData));
 | 
			
		||||
        importRequest.setImportSettings(EntityImportSettings.builder()
 | 
			
		||||
                .updateReferencesToOtherEntities(false)
 | 
			
		||||
                .build());
 | 
			
		||||
        importedDashboard = (Dashboard) importEntities(importRequest).get(0).getSavedEntity();
 | 
			
		||||
 | 
			
		||||
        assertThat(importedDashboard.getConfiguration()).isEqualTo(dashboard.getConfiguration());
 | 
			
		||||
        assertThat(importedDashboard.getAssignedCustomers()).hasOnlyOneElementSatisfying(customerInfo -> {
 | 
			
		||||
            assertThat(customerInfo.getCustomerId()).isEqualTo(importedCustomer.getId());
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportRequests() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
 | 
			
		||||
        Device device = createDevice(tenantId1, null, null, "Device 1");
 | 
			
		||||
        DeviceProfile deviceProfile = createDeviceProfile(tenantId1, null, null, "Device profile 1");
 | 
			
		||||
        RuleChain ruleChain = createRuleChain(tenantId1, "Rule chain 1");
 | 
			
		||||
        Asset asset = createAsset(tenantId1, null, "A", "Asset 1");
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantId1, null, "Dashboard 1");
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "Customer 1");
 | 
			
		||||
 | 
			
		||||
        Map<EntityType, ExportableEntity<?>> entities = Map.of(
 | 
			
		||||
                EntityType.DEVICE, device, EntityType.DEVICE_PROFILE, deviceProfile,
 | 
			
		||||
                EntityType.RULE_CHAIN, ruleChain, EntityType.ASSET, asset,
 | 
			
		||||
                EntityType.DASHBOARD, dashboard, EntityType.CUSTOMER, customer
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        for (ExportableEntity<?> entity : entities.values()) {
 | 
			
		||||
            testEntityTypeExportRequest(entity);
 | 
			
		||||
            testCustomEntityFilterExportRequest(entity);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void testEntityTypeExportRequest(ExportableEntity<?> entity) throws Exception {
 | 
			
		||||
        EntityTypeExportRequest exportRequest = new EntityTypeExportRequest();
 | 
			
		||||
        exportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
        exportRequest.setPageSize(10);
 | 
			
		||||
        exportRequest.setEntityType(entity.getId().getEntityType());
 | 
			
		||||
 | 
			
		||||
    private <E extends ExportableEntity<?> & HasTenantId> void checkImportedEntity(TenantId tenantId1, E initialEntity, TenantId tenantId2, EntityImportResult<E> importResult) {
 | 
			
		||||
        E importedEntity = importResult.getSavedEntity();
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequest);
 | 
			
		||||
        assertThat(exportDataList).size().isNotZero();
 | 
			
		||||
        assertThat(exportDataList).anySatisfy(exportData -> {
 | 
			
		||||
            assertThat(exportData.getEntity()).isEqualTo(entity);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        assertThat(initialEntity.getTenantId()).isEqualTo(tenantId1);
 | 
			
		||||
        assertThat(importedEntity.getTenantId()).isEqualTo(tenantId2);
 | 
			
		||||
    private void testCustomEntityFilterExportRequest(ExportableEntity<?> entity) throws Exception {
 | 
			
		||||
        CustomEntityFilterExportRequest exportRequest = new CustomEntityFilterExportRequest();
 | 
			
		||||
        exportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
        exportRequest.setPageSize(10);
 | 
			
		||||
 | 
			
		||||
        assertThat(importedEntity.getExternalId()).isEqualTo(initialEntity.getId());
 | 
			
		||||
        EntityListFilter filter = new EntityListFilter();
 | 
			
		||||
        filter.setEntityType(entity.getId().getEntityType());
 | 
			
		||||
        filter.setEntityList(List.of(entity.getId().toString()));
 | 
			
		||||
        exportRequest.setFilter(filter);
 | 
			
		||||
 | 
			
		||||
        boolean sameTenant = tenantId1.equals(tenantId2);
 | 
			
		||||
        if (!sameTenant) {
 | 
			
		||||
            assertThat(importedEntity.getId()).isNotEqualTo(initialEntity.getId());
 | 
			
		||||
        } else {
 | 
			
		||||
            assertThat(importedEntity.getId()).isEqualTo(initialEntity.getId());
 | 
			
		||||
            assertThat(importResult.getOldEntity()).isEqualTo(initialEntity);
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequest);
 | 
			
		||||
        assertThat(exportDataList).hasOnlyOneElementSatisfying(exportData -> {
 | 
			
		||||
            assertThat(exportData.getEntity()).isEqualTo(entity);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExportImportCustomerEntities_betweenTenants() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "Customer 1");
 | 
			
		||||
 | 
			
		||||
        Device tenantDevice = createDevice(tenantId1, null, null, "Tenant device 1");
 | 
			
		||||
        Device customerDevice = createDevice(tenantId1, customer.getId(), null, "Customer device 1");
 | 
			
		||||
        Asset tenantAsset = createAsset(tenantId1, null, "A", "Tenant asset 1");
 | 
			
		||||
        Asset customerAsset = createAsset(tenantId1, customer.getId(), "A", "Customer asset 1");
 | 
			
		||||
 | 
			
		||||
        List<ExportRequest> exportRequests = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        for (EntityType entityType : Set.of(EntityType.DEVICE, EntityType.ASSET)) {
 | 
			
		||||
            EntityTypeExportRequest exportRequest = new EntityTypeExportRequest();
 | 
			
		||||
            exportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
            exportRequest.setPageSize(10);
 | 
			
		||||
            exportRequest.setEntityType(entityType);
 | 
			
		||||
            exportRequest.setCustomerId(customer.getId());
 | 
			
		||||
            exportRequests.add(exportRequest);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        List<EntityExportData<?>> exportDataList = exportEntities(exportRequests);
 | 
			
		||||
        assertThat(exportDataList).size().isEqualTo(2);
 | 
			
		||||
        assertThat(exportDataList).anySatisfy(exportData -> {
 | 
			
		||||
            assertThat(exportData.getEntity()).isEqualTo(customerDevice);
 | 
			
		||||
        });
 | 
			
		||||
        assertThat(exportDataList).anySatisfy(exportData -> {
 | 
			
		||||
            assertThat(exportData.getEntity()).isEqualTo(customerAsset);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private void logInAsTenantAdmin1() throws Exception {
 | 
			
		||||
        login(tenantAdmin1.getEmail(), "12345678");
 | 
			
		||||
    }
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testEntityEventsOnImport() throws Exception {
 | 
			
		||||
        logInAsTenantAdmin1();
 | 
			
		||||
 | 
			
		||||
    private void logInAsTenantAdmin2() throws Exception {
 | 
			
		||||
        login(tenantAdmin2.getEmail(), "12345678");
 | 
			
		||||
        Customer customer = createCustomer(tenantId1, "Customer 1");
 | 
			
		||||
        Asset asset = createAsset(tenantId1, null, "A", "Asset 1");
 | 
			
		||||
        RuleChain ruleChain = createRuleChain(tenantId1, "Rule chain 1");
 | 
			
		||||
        Dashboard dashboard = createDashboard(tenantId1, null, "Dashboard 1");
 | 
			
		||||
        DeviceProfile deviceProfile = createDeviceProfile(tenantId1, ruleChain.getId(), dashboard.getId(), "Device profile 1");
 | 
			
		||||
        Device device = createDevice(tenantId1, null, deviceProfile.getId(), "Device 1");
 | 
			
		||||
 | 
			
		||||
        EntityListExportRequest exportRequest = new EntityListExportRequest();
 | 
			
		||||
        exportRequest.setEntitiesIds(List.of(customer.getId(), asset.getId(), device.getId(), ruleChain.getId(), dashboard.getId(), deviceProfile.getId()));
 | 
			
		||||
        exportRequest.setExportSettings(new EntityExportSettings());
 | 
			
		||||
 | 
			
		||||
        Map<EntityType, EntityExportData> entitiesExportData = exportEntities(exportRequest).stream()
 | 
			
		||||
                .collect(Collectors.toMap(EntityExportData::getEntityType, r -> r));
 | 
			
		||||
 | 
			
		||||
        logInAsTenantAdmin2();
 | 
			
		||||
 | 
			
		||||
        Customer importedCustomer = (Customer) importEntity(entitiesExportData.get(EntityType.CUSTOMER)).getSavedEntity();
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedCustomer.getId()), eq(importedCustomer),
 | 
			
		||||
                any(), eq(ActionType.ADDED), isNull());
 | 
			
		||||
        importEntity(entitiesExportData.get(EntityType.CUSTOMER));
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedCustomer.getId()), eq(importedCustomer),
 | 
			
		||||
                any(), eq(ActionType.UPDATED), isNull());
 | 
			
		||||
        verify(clusterService).sendNotificationMsgToEdgeService(any(), any(), eq(importedCustomer.getId()), any(), any(), eq(EdgeEventActionType.UPDATED));
 | 
			
		||||
 | 
			
		||||
        Asset importedAsset = (Asset) importEntity(entitiesExportData.get(EntityType.ASSET)).getSavedEntity();
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedAsset.getId()), eq(importedAsset),
 | 
			
		||||
                any(), eq(ActionType.ADDED), isNull());
 | 
			
		||||
        importEntity(entitiesExportData.get(EntityType.ASSET));
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedAsset.getId()), eq(importedAsset),
 | 
			
		||||
                any(), eq(ActionType.UPDATED), isNull());
 | 
			
		||||
        verify(clusterService).sendNotificationMsgToEdgeService(any(), any(), eq(importedAsset.getId()), any(), any(), eq(EdgeEventActionType.UPDATED));
 | 
			
		||||
 | 
			
		||||
        RuleChain importedRuleChain = (RuleChain) importEntity(entitiesExportData.get(EntityType.RULE_CHAIN)).getSavedEntity();
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedRuleChain.getId()), eq(importedRuleChain),
 | 
			
		||||
                any(), eq(ActionType.ADDED), isNull());
 | 
			
		||||
        verify(clusterService).broadcastEntityStateChangeEvent(any(), eq(importedRuleChain.getId()), eq(ComponentLifecycleEvent.CREATED));
 | 
			
		||||
 | 
			
		||||
        Dashboard importedDashboard = (Dashboard) importEntity(entitiesExportData.get(EntityType.DASHBOARD)).getSavedEntity();
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedDashboard.getId()), eq(importedDashboard),
 | 
			
		||||
                any(), eq(ActionType.ADDED), isNull());
 | 
			
		||||
 | 
			
		||||
        DeviceProfile importedDeviceProfile = (DeviceProfile) importEntity(entitiesExportData.get(EntityType.DEVICE_PROFILE)).getSavedEntity();
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedDeviceProfile.getId()), eq(importedDeviceProfile),
 | 
			
		||||
                any(), eq(ActionType.ADDED), isNull());
 | 
			
		||||
        verify(clusterService).onDeviceProfileChange(eq(importedDeviceProfile), any());
 | 
			
		||||
        verify(clusterService).broadcastEntityStateChangeEvent(any(), eq(importedDeviceProfile.getId()), eq(ComponentLifecycleEvent.CREATED));
 | 
			
		||||
        verify(clusterService).sendNotificationMsgToEdgeService(any(), any(), eq(importedDeviceProfile.getId()), any(), any(), eq(EdgeEventActionType.ADDED));
 | 
			
		||||
        verify(otaPackageStateService).update(eq(importedDeviceProfile), eq(false), eq(false));
 | 
			
		||||
 | 
			
		||||
        ((DeviceExportData)entitiesExportData.get(EntityType.DEVICE)).getCredentials().setCredentialsId("abc");
 | 
			
		||||
        Device importedDevice = (Device) importEntity(entitiesExportData.get(EntityType.DEVICE)).getSavedEntity();
 | 
			
		||||
        verify(entityActionService).logEntityAction(any(), eq(importedDevice.getId()), eq(importedDevice),
 | 
			
		||||
                any(), eq(ActionType.ADDED), isNull());
 | 
			
		||||
        verify(clusterService).onDeviceUpdated(eq(importedDevice), isNull());
 | 
			
		||||
        importEntity(entitiesExportData.get(EntityType.DEVICE));
 | 
			
		||||
        verify(clusterService).onDeviceUpdated(eq(importedDevice), eq(importedDevice));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -26,4 +26,7 @@ public interface ExportableEntity<I extends EntityId> extends HasId<I>, HasName
 | 
			
		||||
    I getExternalId();
 | 
			
		||||
    void setExternalId(I externalId);
 | 
			
		||||
 | 
			
		||||
    long getCreatedTime();
 | 
			
		||||
    void setCreatedTime(long createdTime);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user