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()));
|
customerInfo.setCustomerId(getExternalIdOrElseInternal(ctx, customerInfo.getCustomerId()));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (dashboard.getEntityAliasesConfig() != null) {
|
|
||||||
for (JsonNode entityAlias : dashboard.getEntityAliasesConfig()) {
|
for (JsonNode entityAlias : dashboard.getEntityAliasesConfig()) {
|
||||||
replaceUuidsRecursively(ctx, entityAlias, Collections.singleton("id"));
|
replaceUuidsRecursively(ctx, entityAlias, Collections.emptySet());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (JsonNode widgetConfig : dashboard.getWidgetsConfig()) {
|
for (JsonNode widgetConfig : dashboard.getWidgetsConfig()) {
|
||||||
replaceUuidsRecursively(ctx, JacksonUtil.getSafely(widgetConfig, "config", "actions"), Collections.singleton("id"));
|
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.setId(ctx.getExternalId(ruleNode.getId()));
|
||||||
ruleNode.setCreatedTime(0);
|
ruleNode.setCreatedTime(0);
|
||||||
ruleNode.setExternalId(null);
|
ruleNode.setExternalId(null);
|
||||||
JsonNode ruleNodeConfig = ruleNode.getConfiguration();
|
replaceUuidsRecursively(ctx, ruleNode.getConfiguration(), Collections.emptySet());
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
|
Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
|
||||||
.forEach(ruleChainConnectionInfo -> {
|
.forEach(ruleChainConnectionInfo -> {
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.service.sync.ie.importing.impl;
|
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.api.client.util.Objects;
|
||||||
import com.google.common.util.concurrent.FutureCallback;
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -23,6 +24,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
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.common.util.JacksonUtil;
|
||||||
import org.thingsboard.server.cluster.TbClusterService;
|
import org.thingsboard.server.cluster.TbClusterService;
|
||||||
import org.thingsboard.server.common.data.Device;
|
import org.thingsboard.server.common.data.Device;
|
||||||
import org.thingsboard.server.common.data.EntityType;
|
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.security.model.SecurityUser;
|
||||||
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
|
import org.thingsboard.server.service.sync.ie.exporting.ExportableEntitiesService;
|
||||||
import org.thingsboard.server.service.sync.ie.importing.EntityImportService;
|
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.sync.vc.data.EntitiesImportCtx;
|
||||||
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
|
import org.thingsboard.server.service.telemetry.TelemetrySubscriptionService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
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);
|
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.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.TenantId;
|
import org.thingsboard.server.common.data.id.TenantId;
|
||||||
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
|
import org.thingsboard.server.common.data.sync.ie.EntityExportData;
|
||||||
import org.thingsboard.server.dao.dashboard.DashboardService;
|
import org.thingsboard.server.dao.dashboard.DashboardService;
|
||||||
@ -72,21 +73,11 @@ public class DashboardImportService extends BaseEntityImportService<DashboardId,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Dashboard prepare(EntitiesImportCtx ctx, Dashboard dashboard, Dashboard old, EntityExportData<Dashboard> exportData, IdProvider idProvider) {
|
protected Dashboard prepare(EntitiesImportCtx ctx, Dashboard dashboard, Dashboard old, EntityExportData<Dashboard> exportData, IdProvider idProvider) {
|
||||||
JsonNode configuration = dashboard.getConfiguration();
|
for (JsonNode entityAlias : dashboard.getEntityAliasesConfig()) {
|
||||||
JsonNode entityAliases = configuration.get("entityAliases");
|
replaceIdsRecursively(ctx, idProvider, entityAlias, Collections.emptySet(), HINTS);
|
||||||
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 widgetConfig : dashboard.getWidgetsConfig()) {
|
||||||
|
replaceIdsRecursively(ctx, idProvider, JacksonUtil.getSafely(widgetConfig, "config", "actions"), Collections.singleton("id"), HINTS);
|
||||||
}
|
}
|
||||||
return dashboard;
|
return dashboard;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -93,16 +93,7 @@ public class RuleChainImportService extends BaseEntityImportService<RuleChainId,
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ruleNodes.forEach(ruleNode -> {
|
ruleNodes.forEach(ruleNode -> replaceIdsRecursively(ctx, idProvider, ruleNode.getConfiguration(), Collections.emptySet(), HINTS));
|
||||||
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);
|
|
||||||
});
|
|
||||||
Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
|
Optional.ofNullable(metaData.getRuleChainConnections()).orElse(Collections.emptyList())
|
||||||
.forEach(ruleChainConnectionInfo -> {
|
.forEach(ruleChainConnectionInfo -> {
|
||||||
ruleChainConnectionInfo.setTargetRuleChainId(idProvider.getInternalId(ruleChainConnectionInfo.getTargetRuleChainId(), false));
|
ruleChainConnectionInfo.setTargetRuleChainId(idProvider.getInternalId(ruleChainConnectionInfo.getTargetRuleChainId(), false));
|
||||||
|
|||||||
@ -73,16 +73,19 @@ public class Dashboard extends DashboardInfo implements ExportableEntity<Dashboa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public ObjectNode getEntityAliasesConfig() {
|
public List<ObjectNode> getEntityAliasesConfig() {
|
||||||
return (ObjectNode) Optional.ofNullable(configuration)
|
return getChildObjects("entityAliases");
|
||||||
.map(config -> config.get("entityAliases"))
|
|
||||||
.filter(JsonNode::isObject).orElse(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public List<ObjectNode> getWidgetsConfig() {
|
public List<ObjectNode> getWidgetsConfig() {
|
||||||
|
return getChildObjects("widgets");
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private List<ObjectNode> getChildObjects(String propertyName) {
|
||||||
return Optional.ofNullable(configuration)
|
return Optional.ofNullable(configuration)
|
||||||
.map(config -> config.get("widgets"))
|
.map(config -> config.get(propertyName))
|
||||||
.filter(node -> !node.isEmpty())
|
.filter(node -> !node.isEmpty())
|
||||||
.map(node -> (ObjectNode) node)
|
.map(node -> (ObjectNode) node)
|
||||||
.map(object -> {
|
.map(object -> {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user