Improvements for import of rule chains and dashboards
This commit is contained in:
		
							parent
							
								
									a1d62373c9
								
							
						
					
					
						commit
						335b4ef465
					
				@ -96,6 +96,9 @@ public class DefaultExportableEntitiesService implements ExportableEntitiesServi
 | 
				
			|||||||
    public <E extends HasId<I>, I extends EntityId> E findEntityByTenantIdAndId(TenantId tenantId, I id) {
 | 
					    public <E extends HasId<I>, I extends EntityId> E findEntityByTenantIdAndId(TenantId tenantId, I id) {
 | 
				
			||||||
        EntityType entityType = id.getEntityType();
 | 
					        EntityType entityType = id.getEntityType();
 | 
				
			||||||
        Dao<E> dao = getDao(entityType);
 | 
					        Dao<E> dao = getDao(entityType);
 | 
				
			||||||
 | 
					        if (dao == null) {
 | 
				
			||||||
 | 
					            throw new IllegalArgumentException("Unsupported entity type " + entityType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        E entity = dao.findById(tenantId, id.getId());
 | 
					        E entity = dao.findById(tenantId, id.getId());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,11 +20,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 | 
				
			|||||||
import org.springframework.context.annotation.Lazy;
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
import org.springframework.transaction.annotation.Transactional;
 | 
					import org.springframework.transaction.annotation.Transactional;
 | 
				
			||||||
import org.thingsboard.server.cluster.TbClusterService;
 | 
					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.ExportableEntity;
 | 
				
			||||||
import org.thingsboard.server.common.data.HasCustomerId;
 | 
					import org.thingsboard.server.common.data.HasCustomerId;
 | 
				
			||||||
import org.thingsboard.server.common.data.audit.ActionType;
 | 
					import org.thingsboard.server.common.data.audit.ActionType;
 | 
				
			||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
					import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
					import org.thingsboard.server.common.data.id.EntityId;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.id.EntityIdFactory;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.HasId;
 | 
					import org.thingsboard.server.common.data.id.HasId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
import org.thingsboard.server.common.data.relation.EntityRelation;
 | 
					import org.thingsboard.server.common.data.relation.EntityRelation;
 | 
				
			||||||
@ -42,6 +44,7 @@ import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
 | 
				
			|||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					import java.util.UUID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract class BaseEntityImportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> implements EntityImportService<I, E, D> {
 | 
					public abstract class BaseEntityImportService<I extends EntityId, E extends ExportableEntity<I>, D extends EntityExportData<E>> implements EntityImportService<I, E, D> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -201,6 +204,27 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
 | 
				
			|||||||
            return entity.getId();
 | 
					            return entity.getId();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Optional<EntityId> getInternalIdByUuid(UUID externalUuid) {
 | 
				
			||||||
 | 
					            for (EntityType entityType : EntityType.values()) {
 | 
				
			||||||
 | 
					                EntityId externalId;
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    externalId = EntityIdFactory.getByTypeAndUuid(entityType, externalUuid);
 | 
				
			||||||
 | 
					                } catch (Exception e) {
 | 
				
			||||||
 | 
					                    continue;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                EntityId internalId = null;
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    internalId = getInternalId(externalId);
 | 
				
			||||||
 | 
					                } catch (Exception ignored) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (internalId != null) {
 | 
				
			||||||
 | 
					                    return Optional.of(internalId);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return Optional.empty();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,6 @@
 | 
				
			|||||||
package org.thingsboard.server.service.sync.importing.impl;
 | 
					package org.thingsboard.server.service.sync.importing.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
					import com.fasterxml.jackson.databind.JsonNode;
 | 
				
			||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
					 | 
				
			||||||
import lombok.RequiredArgsConstructor;
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
import org.thingsboard.common.util.JacksonUtil;
 | 
					import org.thingsboard.common.util.JacksonUtil;
 | 
				
			||||||
@ -27,22 +26,19 @@ import org.thingsboard.server.common.data.edge.EdgeEventActionType;
 | 
				
			|||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
					import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
					import org.thingsboard.server.common.data.id.CustomerId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.DashboardId;
 | 
					import org.thingsboard.server.common.data.id.DashboardId;
 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.id.EntityIdFactory;
 | 
					 | 
				
			||||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
					import org.thingsboard.server.common.data.id.TenantId;
 | 
				
			||||||
import org.thingsboard.server.common.data.query.EntityFilter;
 | 
					 | 
				
			||||||
import org.thingsboard.server.dao.dashboard.DashboardService;
 | 
					import org.thingsboard.server.dao.dashboard.DashboardService;
 | 
				
			||||||
import org.thingsboard.server.dao.sql.query.DefaultEntityQueryRepository;
 | 
					 | 
				
			||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
					import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
				
			||||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
					import org.thingsboard.server.service.security.model.SecurityUser;
 | 
				
			||||||
import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
 | 
					import org.thingsboard.server.service.sync.exporting.data.EntityExportData;
 | 
				
			||||||
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
 | 
					import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
 | 
				
			||||||
 | 
					import org.thingsboard.server.utils.RegexUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.regex.Pattern;
 | 
					import java.util.UUID;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Service
 | 
					@Service
 | 
				
			||||||
@ -52,7 +48,6 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private final DashboardService dashboardService;
 | 
					    private final DashboardService dashboardService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    protected void setOwner(TenantId tenantId, Dashboard dashboard, IdProvider idProvider) {
 | 
					    protected void setOwner(TenantId tenantId, Dashboard dashboard, IdProvider idProvider) {
 | 
				
			||||||
@ -70,25 +65,13 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    protected Dashboard prepareAndSave(TenantId tenantId, Dashboard dashboard, EntityExportData<Dashboard> exportData, IdProvider idProvider) {
 | 
					    protected Dashboard prepareAndSave(TenantId tenantId, Dashboard dashboard, EntityExportData<Dashboard> exportData, IdProvider idProvider) {
 | 
				
			||||||
        Optional.ofNullable(dashboard.getConfiguration())
 | 
					        JsonNode configuration = dashboard.getConfiguration();
 | 
				
			||||||
                .flatMap(configuration -> Optional.ofNullable(configuration.get("entityAliases")))
 | 
					        String newConfigurationJson = RegexUtils.replace(configuration.toString(), RegexUtils.UUID_PATTERN, uuid -> {
 | 
				
			||||||
                .filter(JsonNode::isObject)
 | 
					            return idProvider.getInternalIdByUuid(UUID.fromString(uuid))
 | 
				
			||||||
                .ifPresent(entityAliases -> entityAliases.forEach(entityAlias -> {
 | 
					                    .map(entityId -> entityId.getId().toString()).orElse(uuid);
 | 
				
			||||||
                    Optional.ofNullable(entityAlias.get("filter"))
 | 
					        });
 | 
				
			||||||
                            .filter(JsonNode::isObject)
 | 
					        configuration = JacksonUtil.toJsonNode(newConfigurationJson);
 | 
				
			||||||
                            .ifPresent(filter -> {
 | 
					        dashboard.setConfiguration(configuration);
 | 
				
			||||||
                                EntityFilter entityFilter = JacksonUtil.treeToValue(filter, EntityFilter.class);
 | 
					 | 
				
			||||||
                                EntityType entityType = DefaultEntityQueryRepository.resolveEntityType(entityFilter);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                String filterJson = filter.toString();
 | 
					 | 
				
			||||||
                                String newFilterJson = UUID_PATTERN.matcher(filterJson).replaceAll(matchResult -> {
 | 
					 | 
				
			||||||
                                    String uuid = matchResult.group();
 | 
					 | 
				
			||||||
                                    EntityId entityId = EntityIdFactory.getByTypeAndUuid(entityType, uuid);
 | 
					 | 
				
			||||||
                                    return idProvider.getInternalId(entityId).toString();
 | 
					 | 
				
			||||||
                                });
 | 
					 | 
				
			||||||
                                ((ObjectNode) entityAlias).set("filter", JacksonUtil.toJsonNode(newFilterJson));
 | 
					 | 
				
			||||||
                            });
 | 
					 | 
				
			||||||
                }));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Set<ShortCustomerInfo> assignedCustomers = Optional.ofNullable(dashboard.getAssignedCustomers()).orElse(Collections.emptySet()).stream()
 | 
					        Set<ShortCustomerInfo> assignedCustomers = Optional.ofNullable(dashboard.getAssignedCustomers()).orElse(Collections.emptySet()).stream()
 | 
				
			||||||
                .peek(customerInfo -> customerInfo.setCustomerId(idProvider.getInternalId(customerInfo.getCustomerId())))
 | 
					                .peek(customerInfo -> customerInfo.setCustomerId(idProvider.getInternalId(customerInfo.getCustomerId())))
 | 
				
			||||||
 | 
				
			|||||||
@ -16,10 +16,9 @@
 | 
				
			|||||||
package org.thingsboard.server.service.sync.importing.impl;
 | 
					package org.thingsboard.server.service.sync.importing.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
					import com.fasterxml.jackson.databind.JsonNode;
 | 
				
			||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
 | 
					 | 
				
			||||||
import com.fasterxml.jackson.databind.node.TextNode;
 | 
					 | 
				
			||||||
import lombok.RequiredArgsConstructor;
 | 
					import lombok.RequiredArgsConstructor;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					import org.thingsboard.common.util.JacksonUtil;
 | 
				
			||||||
import org.thingsboard.server.common.data.EntityType;
 | 
					import org.thingsboard.server.common.data.EntityType;
 | 
				
			||||||
import org.thingsboard.server.common.data.edge.EdgeEventActionType;
 | 
					import org.thingsboard.server.common.data.edge.EdgeEventActionType;
 | 
				
			||||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
					import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
				
			||||||
@ -29,11 +28,13 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
 | 
				
			|||||||
import org.thingsboard.server.common.data.rule.RuleChain;
 | 
					import org.thingsboard.server.common.data.rule.RuleChain;
 | 
				
			||||||
import org.thingsboard.server.common.data.rule.RuleChainMetaData;
 | 
					import org.thingsboard.server.common.data.rule.RuleChainMetaData;
 | 
				
			||||||
import org.thingsboard.server.common.data.rule.RuleChainType;
 | 
					import org.thingsboard.server.common.data.rule.RuleChainType;
 | 
				
			||||||
 | 
					import org.thingsboard.server.common.data.rule.RuleChainUpdateResult;
 | 
				
			||||||
import org.thingsboard.server.dao.rule.RuleChainService;
 | 
					import org.thingsboard.server.dao.rule.RuleChainService;
 | 
				
			||||||
import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
					import org.thingsboard.server.queue.util.TbCoreComponent;
 | 
				
			||||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
					import org.thingsboard.server.service.security.model.SecurityUser;
 | 
				
			||||||
import org.thingsboard.server.service.sync.exporting.data.RuleChainExportData;
 | 
					import org.thingsboard.server.service.sync.exporting.data.RuleChainExportData;
 | 
				
			||||||
import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
 | 
					import org.thingsboard.server.service.sync.importing.data.EntityImportSettings;
 | 
				
			||||||
 | 
					import org.thingsboard.server.utils.RegexUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
@ -67,16 +68,15 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
 | 
				
			|||||||
                .forEach(ruleNode -> {
 | 
					                .forEach(ruleNode -> {
 | 
				
			||||||
                    ruleNode.setId(null);
 | 
					                    ruleNode.setId(null);
 | 
				
			||||||
                    ruleNode.setRuleChainId(null);
 | 
					                    ruleNode.setRuleChainId(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    JsonNode ruleNodeConfig = ruleNode.getConfiguration();
 | 
					                    JsonNode ruleNodeConfig = ruleNode.getConfiguration();
 | 
				
			||||||
                    Optional.ofNullable(ruleNodeConfig)
 | 
					                    String newRuleNodeConfigJson = RegexUtils.replace(ruleNodeConfig.toString(), RegexUtils.UUID_PATTERN, uuid -> {
 | 
				
			||||||
                            .flatMap(config -> Optional.ofNullable(config.get("ruleChainId")).filter(JsonNode::isTextual))
 | 
					                        return idProvider.getInternalIdByUuid(UUID.fromString(uuid))
 | 
				
			||||||
                            .map(JsonNode::asText).map(UUID::fromString)
 | 
					                                .map(entityId -> entityId.getId().toString())
 | 
				
			||||||
                            .ifPresent(otherRuleChainUuid -> {
 | 
					                                .orElse(uuid);
 | 
				
			||||||
                                ((ObjectNode) ruleNodeConfig).set("ruleChainId", new TextNode(
 | 
					                    });
 | 
				
			||||||
                                        idProvider.getInternalId(new RuleChainId(otherRuleChainUuid)).toString()
 | 
					                    ruleNodeConfig = JacksonUtil.toJsonNode(newRuleNodeConfigJson);
 | 
				
			||||||
                                ));
 | 
					                    ruleNode.setConfiguration(ruleNodeConfig);
 | 
				
			||||||
                                ruleNode.setConfiguration(ruleNodeConfig);
 | 
					 | 
				
			||||||
                            });
 | 
					 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
        Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
 | 
					        Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
 | 
				
			||||||
                .forEach(ruleChainConnectionInfo -> {
 | 
					                .forEach(ruleChainConnectionInfo -> {
 | 
				
			||||||
@ -84,13 +84,10 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
 | 
				
			|||||||
                });
 | 
					                });
 | 
				
			||||||
        ruleChain.setFirstRuleNodeId(null);
 | 
					        ruleChain.setFirstRuleNodeId(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (ruleChain.getId() != null) {
 | 
					 | 
				
			||||||
            // FIXME [viacheslav]: maybe no need to delete
 | 
					 | 
				
			||||||
            ruleChainService.deleteRuleNodes(tenantId, ruleChain.getId());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        ruleChain = ruleChainService.saveRuleChain(ruleChain);
 | 
					        ruleChain = ruleChainService.saveRuleChain(ruleChain);
 | 
				
			||||||
        exportData.getMetaData().setRuleChainId(ruleChain.getId());
 | 
					        exportData.getMetaData().setRuleChainId(ruleChain.getId());
 | 
				
			||||||
        ruleChainService.saveRuleChainMetaData(tenantId, exportData.getMetaData());
 | 
					        RuleChainUpdateResult updateResult = ruleChainService.saveRuleChainMetaData(tenantId, exportData.getMetaData());
 | 
				
			||||||
 | 
					        // FIXME [viacheslav]: send events for nodes
 | 
				
			||||||
        return ruleChainService.findRuleChainById(tenantId, ruleChain.getId());
 | 
					        return ruleChainService.findRuleChainById(tenantId, ruleChain.getId());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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 lombok.AccessLevel;
 | 
				
			||||||
 | 
					import lombok.NoArgsConstructor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.function.UnaryOperator;
 | 
				
			||||||
 | 
					import java.util.regex.Pattern;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@NoArgsConstructor(access = AccessLevel.PRIVATE)
 | 
				
			||||||
 | 
					public class RegexUtils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String replace(String s, Pattern pattern, UnaryOperator<String> replacer) {
 | 
				
			||||||
 | 
					        return pattern.matcher(s).replaceAll(matchResult -> {
 | 
				
			||||||
 | 
					            return replacer.apply(matchResult.group());
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user