Fix import/export of rule chains and dashboard with external id references
This commit is contained in:
		
							parent
							
								
									5cad77910f
								
							
						
					
					
						commit
						bdd8432049
					
				@ -45,10 +45,8 @@ public class DashboardExportService extends BaseEntityExportService<DashboardId,
 | 
			
		||||
                customerInfo.setCustomerId(getExternalIdOrElseInternal(ctx, customerInfo.getCustomerId()));
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
        if (dashboard.getEntityAliasesConfig() != null) {
 | 
			
		||||
            for (JsonNode entityAlias : dashboard.getEntityAliasesConfig()) {
 | 
			
		||||
                replaceUuidsRecursively(ctx, entityAlias, Collections.singleton("id"));
 | 
			
		||||
            }
 | 
			
		||||
        for (JsonNode entityAlias : dashboard.getEntityAliasesConfig()) {
 | 
			
		||||
            replaceUuidsRecursively(ctx, entityAlias, Collections.emptySet());
 | 
			
		||||
        }
 | 
			
		||||
        for (JsonNode widgetConfig : dashboard.getWidgetsConfig()) {
 | 
			
		||||
            replaceUuidsRecursively(ctx, JacksonUtil.getSafely(widgetConfig, "config", "actions"), Collections.singleton("id"));
 | 
			
		||||
 | 
			
		||||
@ -51,12 +51,7 @@ public class RuleChainExportService extends BaseEntityExportService<RuleChainId,
 | 
			
		||||
                    ruleNode.setId(ctx.getExternalId(ruleNode.getId()));
 | 
			
		||||
                    ruleNode.setCreatedTime(0);
 | 
			
		||||
                    ruleNode.setExternalId(null);
 | 
			
		||||
                    JsonNode ruleNodeConfig = ruleNode.getConfiguration();
 | 
			
		||||
                    String newRuleNodeConfigJson = RegexUtils.replace(JacksonUtil.toString(ruleNodeConfig), RegexUtils.UUID_PATTERN, uuid -> {
 | 
			
		||||
                        return getExternalIdOrElseInternalByUuid(ctx, UUID.fromString(uuid)).toString();
 | 
			
		||||
                    });
 | 
			
		||||
                    ruleNodeConfig = JacksonUtil.toJsonNode(newRuleNodeConfigJson);
 | 
			
		||||
                    ruleNode.setConfiguration(ruleNodeConfig);
 | 
			
		||||
                    replaceUuidsRecursively(ctx, ruleNode.getConfiguration(), Collections.emptySet());
 | 
			
		||||
                });
 | 
			
		||||
        Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
 | 
			
		||||
                .forEach(ruleChainConnectionInfo -> {
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.service.sync.ie.importing.impl;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.JsonNode;
 | 
			
		||||
import com.google.api.client.util.Objects;
 | 
			
		||||
import com.google.common.util.concurrent.FutureCallback;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
@ -23,6 +24,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.context.annotation.Lazy;
 | 
			
		||||
import org.springframework.transaction.annotation.Transactional;
 | 
			
		||||
import org.thingsboard.common.util.JacksonUtil;
 | 
			
		||||
import org.thingsboard.server.cluster.TbClusterService;
 | 
			
		||||
import org.thingsboard.server.common.data.Device;
 | 
			
		||||
import org.thingsboard.server.common.data.EntityType;
 | 
			
		||||
@ -53,11 +55,13 @@ import org.thingsboard.server.service.entitiy.TbNotificationEntityService;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
 | 
			
		||||
import org.thingsboard.server.service.sync.ie.importing.EntityImportService;
 | 
			
		||||
import org.thingsboard.server.service.sync.vc.data.EntitiesExportCtx;
 | 
			
		||||
import org.thingsboard.server.service.sync.vc.data.EntitiesImportCtx;
 | 
			
		||||
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.LinkedHashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
@ -386,4 +390,9 @@ public abstract class BaseEntityImportService<I extends EntityId, E extends Expo
 | 
			
		||||
        return oldEntity == null ? null : getter.apply(oldEntity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void replaceIdsRecursively(EntitiesImportCtx ctx, IdProvider idProvider, JsonNode entityAlias, Set<String> skipFieldsSet, LinkedHashSet<EntityType> hints) {
 | 
			
		||||
        JacksonUtil.replaceUuidsRecursively(entityAlias, skipFieldsSet,
 | 
			
		||||
                uuid -> idProvider.getInternalIdByUuid(uuid, ctx.isFinalImportAttempt(), hints).map(EntityId::getId).orElse(uuid));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -28,6 +28,7 @@ import org.thingsboard.server.common.data.edge.EdgeEventActionType;
 | 
			
		||||
import org.thingsboard.server.common.data.exception.ThingsboardException;
 | 
			
		||||
import org.thingsboard.server.common.data.id.CustomerId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.DashboardId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.EntityId;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
 | 
			
		||||
import org.thingsboard.server.dao.dashboard.DashboardService;
 | 
			
		||||
@ -72,21 +73,11 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected Dashboard prepare(EntitiesImportCtx ctx, Dashboard dashboard, Dashboard old, EntityExportData<Dashboard> exportData, IdProvider idProvider) {
 | 
			
		||||
        JsonNode configuration = dashboard.getConfiguration();
 | 
			
		||||
        JsonNode entityAliases = configuration.get("entityAliases");
 | 
			
		||||
        if (entityAliases != null && entityAliases.isObject()) {
 | 
			
		||||
            for (JsonNode entityAlias : entityAliases) {
 | 
			
		||||
                ArrayList<String> fields = Lists.newArrayList(entityAlias.fieldNames());
 | 
			
		||||
                for (String field : fields) {
 | 
			
		||||
                    if (field.equals("id")) continue;
 | 
			
		||||
                    JsonNode oldFieldValue = entityAlias.get(field);
 | 
			
		||||
                    JsonNode newFieldValue = JacksonUtil.toJsonNode(RegexUtils.replace(oldFieldValue.toString(), RegexUtils.UUID_PATTERN, uuid -> {
 | 
			
		||||
                        return idProvider.getInternalIdByUuid(UUID.fromString(uuid), ctx.isFinalImportAttempt(), HINTS)
 | 
			
		||||
                                .map(entityId -> entityId.getId().toString()).orElse(uuid);
 | 
			
		||||
                    }));
 | 
			
		||||
                    ((ObjectNode) entityAlias).set(field, newFieldValue);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        for (JsonNode entityAlias : dashboard.getEntityAliasesConfig()) {
 | 
			
		||||
            replaceIdsRecursively(ctx, idProvider, entityAlias, Collections.emptySet(), HINTS);
 | 
			
		||||
        }
 | 
			
		||||
        for (JsonNode widgetConfig : dashboard.getWidgetsConfig()) {
 | 
			
		||||
            replaceIdsRecursively(ctx, idProvider, JacksonUtil.getSafely(widgetConfig, "config", "actions"), Collections.singleton("id"), HINTS);
 | 
			
		||||
        }
 | 
			
		||||
        return dashboard;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -93,16 +93,7 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ruleNodes.forEach(ruleNode -> {
 | 
			
		||||
            JsonNode ruleNodeConfig = ruleNode.getConfiguration();
 | 
			
		||||
            String newRuleNodeConfigJson = RegexUtils.replace(JacksonUtil.toString(ruleNodeConfig), RegexUtils.UUID_PATTERN, uuid -> {
 | 
			
		||||
                return idProvider.getInternalIdByUuid(UUID.fromString(uuid), ctx.isFinalImportAttempt(), HINTS)
 | 
			
		||||
                        .map(entityId -> entityId.getId().toString())
 | 
			
		||||
                        .orElse(uuid);
 | 
			
		||||
            });
 | 
			
		||||
            ruleNodeConfig = JacksonUtil.toJsonNode(newRuleNodeConfigJson);
 | 
			
		||||
            ruleNode.setConfiguration(ruleNodeConfig);
 | 
			
		||||
        });
 | 
			
		||||
        ruleNodes.forEach(ruleNode -> replaceIdsRecursively(ctx, idProvider, ruleNode.getConfiguration(), Collections.emptySet(), HINTS));
 | 
			
		||||
        Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
 | 
			
		||||
                .forEach(ruleChainConnectionInfo -> {
 | 
			
		||||
                    ruleChainConnectionInfo.setTargetRuleChainId(idProvider.getInternalId(ruleChainConnectionInfo.getTargetRuleChainId(), false));
 | 
			
		||||
 | 
			
		||||
@ -73,16 +73,19 @@ public class Dashboard extends DashboardInfo implements ExportableEntity<Dashboa
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    public ObjectNode getEntityAliasesConfig() {
 | 
			
		||||
        return (ObjectNode) Optional.ofNullable(configuration)
 | 
			
		||||
                .map(config -> config.get("entityAliases"))
 | 
			
		||||
                .filter(JsonNode::isObject).orElse(null);
 | 
			
		||||
    public List<ObjectNode> getEntityAliasesConfig() {
 | 
			
		||||
        return getChildObjects("entityAliases");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    public List<ObjectNode> getWidgetsConfig() {
 | 
			
		||||
        return getChildObjects("widgets");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    private List<ObjectNode> getChildObjects(String propertyName) {
 | 
			
		||||
        return Optional.ofNullable(configuration)
 | 
			
		||||
                .map(config -> config.get("widgets"))
 | 
			
		||||
                .map(config -> config.get(propertyName))
 | 
			
		||||
                .filter(node -> !node.isEmpty())
 | 
			
		||||
                .map(node -> (ObjectNode) node)
 | 
			
		||||
                .map(object -> {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user