Merge pull request #13322 from thingsboard/feature/rule-chain-relation

Automatic relations creation between Rule Chains when adding "Rule Chain" node
This commit is contained in:
Viacheslav Klimov 2025-05-07 12:22:08 +03:00 committed by GitHub
commit 3f933c8b45
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 180 additions and 29 deletions

View File

@ -25,21 +25,30 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.alarm.AlarmSeverity; import org.thingsboard.server.common.data.alarm.AlarmSeverity;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageDataIterable; import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.query.DynamicValue; import org.thingsboard.server.common.data.query.DynamicValue;
import org.thingsboard.server.common.data.query.FilterPredicateValue; import org.thingsboard.server.common.data.query.FilterPredicateValue;
import org.thingsboard.server.common.data.relation.EntityRelation;
import org.thingsboard.server.common.data.relation.RelationTypeGroup;
import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleChainService;
import org.thingsboard.server.dao.sql.JpaExecutorService;
import org.thingsboard.server.service.component.ComponentDiscoveryService; import org.thingsboard.server.service.component.ComponentDiscoveryService;
import org.thingsboard.server.service.component.RuleNodeClassInfo; import org.thingsboard.server.service.component.RuleNodeClassInfo;
import org.thingsboard.server.service.install.DbUpgradeExecutorService;
import org.thingsboard.server.utils.TbNodeUpgradeUtils; import org.thingsboard.server.utils.TbNodeUpgradeUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import static org.thingsboard.server.dao.rule.BaseRuleChainService.TB_RULE_CHAIN_INPUT_NODE;
@Service @Service
@Profile("install") @Profile("install")
@Slf4j @Slf4j
@ -51,19 +60,50 @@ public class DefaultDataUpdateService implements DataUpdateService {
@Autowired @Autowired
private RuleChainService ruleChainService; private RuleChainService ruleChainService;
@Autowired
private RelationService relationService;
@Autowired @Autowired
private ComponentDiscoveryService componentDiscoveryService; private ComponentDiscoveryService componentDiscoveryService;
@Autowired @Autowired
JpaExecutorService jpaExecutorService; private DbUpgradeExecutorService executorService;
@Override @Override
public void updateData() throws Exception { public void updateData() throws Exception {
log.info("Updating data ..."); log.info("Updating data ...");
//TODO: should be cleaned after each release //TODO: should be cleaned after each release
updateInputNodes();
log.info("Data updated."); log.info("Data updated.");
} }
private void updateInputNodes() {
log.info("Creating relations for input nodes...");
int n = 0;
var inputNodes = new PageDataIterable<>(pageLink -> ruleChainService.findAllRuleNodesByType(TB_RULE_CHAIN_INPUT_NODE, pageLink), 1024);
for (RuleNode inputNode : inputNodes) {
try {
RuleChainId targetRuleChainId = Optional.ofNullable(inputNode.getConfiguration().get("ruleChainId"))
.filter(JsonNode::isTextual).map(JsonNode::asText).map(id -> new RuleChainId(UUID.fromString(id)))
.orElse(null);
if (targetRuleChainId == null) {
continue;
}
EntityRelation relation = new EntityRelation();
relation.setFrom(inputNode.getRuleChainId());
relation.setTo(targetRuleChainId);
relation.setType(EntityRelation.USES_TYPE);
relation.setTypeGroup(RelationTypeGroup.COMMON);
relationService.saveRelation(TenantId.SYS_TENANT_ID, relation);
n++;
} catch (Exception e) {
log.error("Failed to save relation for input node: {}", inputNode, e);
}
}
log.info("Created {} relations for input nodes", n);
}
@Override @Override
public void upgradeRuleNodes() { public void upgradeRuleNodes() {
int totalRuleNodesUpgraded = 0; int totalRuleNodesUpgraded = 0;
@ -107,7 +147,7 @@ public class DefaultDataUpdateService implements DataUpdateService {
ruleNodeId, ruleNodeType, fromVersion, toVersion); ruleNodeId, ruleNodeType, fromVersion, toVersion);
try { try {
TbNodeUpgradeUtils.upgradeConfigurationAndVersion(ruleNode, ruleNodeClassInfo); TbNodeUpgradeUtils.upgradeConfigurationAndVersion(ruleNode, ruleNodeClassInfo);
saveFutures.add(jpaExecutorService.submit(() -> { saveFutures.add(executorService.submit(() -> {
ruleChainService.saveRuleNode(TenantId.SYS_TENANT_ID, ruleNode); ruleChainService.saveRuleNode(TenantId.SYS_TENANT_ID, ruleNode);
log.debug("Successfully upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}", log.debug("Successfully upgrade rule node with id: {} type: {} fromVersion: {} toVersion: {}",
ruleNodeId, ruleNodeType, fromVersion, toVersion); ruleNodeId, ruleNodeType, fromVersion, toVersion);

View File

@ -43,6 +43,7 @@ public class EntityRelation implements HasVersion, Serializable, EdqsObject {
public static final String EDGE_TYPE = "ManagedByEdge"; public static final String EDGE_TYPE = "ManagedByEdge";
public static final String CONTAINS_TYPE = "Contains"; public static final String CONTAINS_TYPE = "Contains";
public static final String MANAGES_TYPE = "Manages"; public static final String MANAGES_TYPE = "Manages";
public static final String USES_TYPE = "Uses";
@Setter @Setter
private EntityId from; private EntityId from;

View File

@ -76,6 +76,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -204,11 +205,17 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
} }
} }
} }
RuleChainId ruleChainId = ruleChain.getId();
List<RuleNodeUpdateResult> updatedRuleNodes = new ArrayList<>(); List<RuleNodeUpdateResult> updatedRuleNodes = new ArrayList<>();
List<RuleNode> existingRuleNodes = getRuleChainNodes(tenantId, ruleChainMetaData.getRuleChainId()); List<RuleNode> existingRuleNodes = getRuleChainNodes(tenantId, ruleChainMetaData.getRuleChainId());
for (RuleNode existingNode : existingRuleNodes) { for (RuleNode existingNode : existingRuleNodes) {
relationService.deleteEntityRelations(tenantId, existingNode.getId()); relationService.deleteEntityRelations(tenantId, existingNode.getId());
if (existingNode.getType().equals(TB_RULE_CHAIN_INPUT_NODE)) {
EntityRelation relation = getRuleChainInputRelation(ruleChainId, existingNode);
if (relation != null) {
relationService.deleteRelation(tenantId, relation);
}
}
Integer index = ruleNodeIndexMap.get(existingNode.getId()); Integer index = ruleNodeIndexMap.get(existingNode.getId());
RuleNode newRuleNode = null; RuleNode newRuleNode = null;
if (index != null) { if (index != null) {
@ -220,7 +227,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
} }
updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode, newRuleNode)); updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode, newRuleNode));
} }
RuleChainId ruleChainId = ruleChain.getId();
if (nodes != null) { if (nodes != null) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
for (RuleNode node : toAddOrUpdate) { for (RuleNode node : toAddOrUpdate) {
@ -233,6 +240,12 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
RuleNode savedNode = ruleNodeDao.save(tenantId, node); RuleNode savedNode = ruleNodeDao.save(tenantId, node);
relations.add(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(), relations.add(new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(),
EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN)); EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
if (node.getType().equals(TB_RULE_CHAIN_INPUT_NODE)) {
EntityRelation relation = getRuleChainInputRelation(ruleChainId, node);
if (relation != null) {
relations.add(relation);
}
}
int index = nodes.indexOf(node); int index = nodes.indexOf(node);
nodes.set(index, savedNode); nodes.set(index, savedNode);
ruleNodeIndexMap.put(savedNode.getId(), index); ruleNodeIndexMap.put(savedNode.getId(), index);
@ -247,7 +260,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
firstRuleNodeId = nodes.get(ruleChainMetaData.getFirstNodeIndex()).getId(); firstRuleNodeId = nodes.get(ruleChainMetaData.getFirstNodeIndex()).getId();
} }
if ((ruleChain.getFirstRuleNodeId() != null && !ruleChain.getFirstRuleNodeId().equals(firstRuleNodeId)) if ((ruleChain.getFirstRuleNodeId() != null && !ruleChain.getFirstRuleNodeId().equals(firstRuleNodeId))
|| (ruleChain.getFirstRuleNodeId() == null && firstRuleNodeId != null)) { || (ruleChain.getFirstRuleNodeId() == null && firstRuleNodeId != null)) {
ruleChain.setFirstRuleNodeId(firstRuleNodeId); ruleChain.setFirstRuleNodeId(firstRuleNodeId);
} }
if (ruleChainMetaData.getConnections() != null) { if (ruleChainMetaData.getConnections() != null) {
@ -265,7 +278,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
RuleNode targetNode = new RuleNode(); RuleNode targetNode = new RuleNode();
targetNode.setName(targetRuleChain != null ? targetRuleChain.getName() : "Rule Chain Input"); targetNode.setName(targetRuleChain != null ? targetRuleChain.getName() : "Rule Chain Input");
targetNode.setRuleChainId(ruleChainId); targetNode.setRuleChainId(ruleChainId);
targetNode.setType("org.thingsboard.rule.engine.flow.TbRuleChainInputNode"); targetNode.setType(TB_RULE_CHAIN_INPUT_NODE);
var configuration = JacksonUtil.newObjectNode(); var configuration = JacksonUtil.newObjectNode();
configuration.put("ruleChainId", targetRuleChainId.getId().toString()); configuration.put("ruleChainId", targetRuleChainId.getId().toString());
targetNode.setConfiguration(configuration); targetNode.setConfiguration(configuration);
@ -302,6 +315,22 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
return RuleChainUpdateResult.successful(updatedRuleNodes); return RuleChainUpdateResult.successful(updatedRuleNodes);
} }
private EntityRelation getRuleChainInputRelation(RuleChainId ruleChainId, RuleNode inputNode) {
RuleChainId targetRuleChainId = Optional.ofNullable(inputNode.getConfiguration().get("ruleChainId"))
.filter(JsonNode::isTextual).map(JsonNode::asText).map(id -> new RuleChainId(UUID.fromString(id)))
.orElse(null);
if (targetRuleChainId != null) {
EntityRelation relation = new EntityRelation();
relation.setFrom(ruleChainId);
relation.setTo(targetRuleChainId);
relation.setType(EntityRelation.USES_TYPE);
relation.setTypeGroup(RelationTypeGroup.COMMON);
return relation;
} else {
return null;
}
}
@Override @Override
public RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId) { public RuleChainMetaData loadRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId) {
Validator.validateId(ruleChainId, "Incorrect rule chain id."); Validator.validateId(ruleChainId, "Incorrect rule chain id.");

View File

@ -28,12 +28,14 @@ import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.relation.EntityRelation; 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.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.RuleNode; import org.thingsboard.server.common.data.rule.RuleNode;
import org.thingsboard.server.dao.edge.EdgeService; import org.thingsboard.server.dao.edge.EdgeService;
import org.thingsboard.server.dao.exception.DataValidationException; import org.thingsboard.server.dao.exception.DataValidationException;
import org.thingsboard.server.dao.relation.RelationService;
import org.thingsboard.server.dao.rule.RuleChainService; import org.thingsboard.server.dao.rule.RuleChainService;
import java.io.IOException; import java.io.IOException;
@ -43,7 +45,10 @@ import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.function.Function; import java.util.function.Function;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.thingsboard.server.common.data.relation.EntityRelation.USES_TYPE;
import static org.thingsboard.server.dao.rule.BaseRuleChainService.TB_RULE_CHAIN_INPUT_NODE;
/** /**
* Created by igor on 3/13/18. * Created by igor on 3/13/18.
@ -55,6 +60,8 @@ public class RuleChainServiceTest extends AbstractServiceTest {
EdgeService edgeService; EdgeService edgeService;
@Autowired @Autowired
RuleChainService ruleChainService; RuleChainService ruleChainService;
@Autowired
RelationService relationService;
private IdComparator<RuleChain> idComparator = new IdComparator<>(); private IdComparator<RuleChain> idComparator = new IdComparator<>();
private IdComparator<RuleNode> ruleNodeIdComparator = new IdComparator<>(); private IdComparator<RuleNode> ruleNodeIdComparator = new IdComparator<>();
@ -270,7 +277,7 @@ public class RuleChainServiceTest extends AbstractServiceTest {
List<RuleNode> ruleNodes = savedRuleChainMetaData.getNodes(); List<RuleNode> ruleNodes = savedRuleChainMetaData.getNodes();
int name3Index = -1; int name3Index = -1;
for (int i=0;i<ruleNodes.size();i++) { for (int i = 0; i < ruleNodes.size(); i++) {
if ("name3".equals(ruleNodes.get(i).getName())) { if ("name3".equals(ruleNodes.get(i).getName())) {
name3Index = i; name3Index = i;
break; break;
@ -354,6 +361,80 @@ public class RuleChainServiceTest extends AbstractServiceTest {
Assert.assertTrue(ruleChainById.isRoot()); Assert.assertTrue(ruleChainById.isRoot());
} }
@Test
public void testSaveRuleChainWithInputNode() {
RuleChain fromRuleChain = new RuleChain();
fromRuleChain.setName("From RuleChain");
fromRuleChain.setTenantId(tenantId);
fromRuleChain = ruleChainService.saveRuleChain(fromRuleChain);
RuleChainId fromRuleChainId = fromRuleChain.getId();
RuleChain toRuleChain1 = new RuleChain();
toRuleChain1.setName("To Rule Chain 1");
toRuleChain1.setTenantId(tenantId);
toRuleChain1 = ruleChainService.saveRuleChain(toRuleChain1);
RuleChainId toRuleChain1Id = toRuleChain1.getId();
RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();
ruleChainMetaData.setRuleChainId(fromRuleChainId);
RuleNode toRuleChain1Node = new RuleNode();
toRuleChain1Node.setName("To Rule Chain 1");
toRuleChain1Node.setType(TB_RULE_CHAIN_INPUT_NODE);
toRuleChain1Node.setConfiguration(JacksonUtil.newObjectNode()
.put("ruleChainId", toRuleChain1Id.toString()));
RuleNode toRuleChain1Node2 = new RuleNode();
toRuleChain1Node2.setName("To Rule Chain 1");
toRuleChain1Node2.setType(TB_RULE_CHAIN_INPUT_NODE);
toRuleChain1Node2.setConfiguration(JacksonUtil.newObjectNode()
.put("ruleChainId", toRuleChain1Id.toString()));
List<RuleNode> ruleNodes = new ArrayList<>();
ruleNodes.add(toRuleChain1Node);
ruleNodes.add(toRuleChain1Node2);
ruleChainMetaData.setFirstNodeIndex(0);
ruleChainMetaData.setNodes(ruleNodes);
ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData, Function.identity());
List<EntityRelation> relations = relationService.findByFromAndType(tenantId, fromRuleChainId, USES_TYPE, RelationTypeGroup.COMMON);
assertThat(relations).singleElement().satisfies(relationToRuleChain1 -> {
assertThat(relationToRuleChain1.getFrom()).isEqualTo(fromRuleChainId);
assertThat(relationToRuleChain1.getTo()).isEqualTo(toRuleChain1Id);
});
RuleChain toRuleChain2 = new RuleChain();
toRuleChain2.setName("To Rule Chain 2");
toRuleChain2.setTenantId(tenantId);
toRuleChain2 = ruleChainService.saveRuleChain(toRuleChain2);
RuleChainId toRuleChain2Id = toRuleChain2.getId();
RuleNode toRuleChain2Node = new RuleNode();
toRuleChain2Node.setName("To Rule Chain 2");
toRuleChain2Node.setType(TB_RULE_CHAIN_INPUT_NODE);
toRuleChain2Node.setConfiguration(JacksonUtil.newObjectNode()
.put("ruleChainId", toRuleChain2Id.toString()));
List<RuleNode> newRuleNodes = new ArrayList<>();
newRuleNodes.add(toRuleChain2Node);
newRuleNodes.add(toRuleChain1Node);
ruleChainMetaData = ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId());
ruleChainMetaData.setNodes(newRuleNodes);
ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData, Function.identity());
List<EntityRelation> newRelations = relationService.findByFromAndType(tenantId, fromRuleChainId, USES_TYPE, RelationTypeGroup.COMMON);
assertThat(newRelations).hasSize(2);
assertThat(newRelations).anySatisfy(relationToRuleChain1 -> {
assertThat(relationToRuleChain1.getFrom()).isEqualTo(fromRuleChainId);
assertThat(relationToRuleChain1.getTo()).isEqualTo(toRuleChain1Id);
});
assertThat(newRelations).anySatisfy(relationToRuleChain2 -> {
assertThat(relationToRuleChain2.getFrom()).isEqualTo(fromRuleChainId);
assertThat(relationToRuleChain2.getTo()).isEqualTo(toRuleChain2Id);
});
}
private RuleChainId saveRuleChainAndSetAutoAssignToEdge(String name) { private RuleChainId saveRuleChainAndSetAutoAssignToEdge(String name) {
RuleChain edgeRuleChain = new RuleChain(); RuleChain edgeRuleChain = new RuleChain();
edgeRuleChain.setTenantId(tenantId); edgeRuleChain.setTenantId(tenantId);
@ -395,9 +476,9 @@ public class RuleChainServiceTest extends AbstractServiceTest {
ruleChainMetaData.setFirstNodeIndex(0); ruleChainMetaData.setFirstNodeIndex(0);
ruleChainMetaData.setNodes(ruleNodes); ruleChainMetaData.setNodes(ruleNodes);
ruleChainMetaData.addConnectionInfo(0,1,"success"); ruleChainMetaData.addConnectionInfo(0, 1, "success");
ruleChainMetaData.addConnectionInfo(0,2,"fail"); ruleChainMetaData.addConnectionInfo(0, 2, "fail");
ruleChainMetaData.addConnectionInfo(1,2,"success"); ruleChainMetaData.addConnectionInfo(1, 2, "success");
Assert.assertTrue(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData, Function.identity()).isSuccess()); Assert.assertTrue(ruleChainService.saveRuleChainMetaData(tenantId, ruleChainMetaData, Function.identity()).isSuccess());
return ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId()); return ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaData.getRuleChainId());
@ -434,10 +515,10 @@ public class RuleChainServiceTest extends AbstractServiceTest {
ruleChainMetaData.setFirstNodeIndex(0); ruleChainMetaData.setFirstNodeIndex(0);
ruleChainMetaData.setNodes(ruleNodes); ruleChainMetaData.setNodes(ruleNodes);
ruleChainMetaData.addConnectionInfo(0,1,"success"); ruleChainMetaData.addConnectionInfo(0, 1, "success");
ruleChainMetaData.addConnectionInfo(0,2,"fail"); ruleChainMetaData.addConnectionInfo(0, 2, "fail");
ruleChainMetaData.addConnectionInfo(1,2,"success"); ruleChainMetaData.addConnectionInfo(1, 2, "success");
ruleChainMetaData.addConnectionInfo(2,2,"success"); ruleChainMetaData.addConnectionInfo(2, 2, "success");
return ruleChainMetaData; return ruleChainMetaData;
} }
@ -473,10 +554,10 @@ public class RuleChainServiceTest extends AbstractServiceTest {
ruleChainMetaData.setFirstNodeIndex(0); ruleChainMetaData.setFirstNodeIndex(0);
ruleChainMetaData.setNodes(ruleNodes); ruleChainMetaData.setNodes(ruleNodes);
ruleChainMetaData.addConnectionInfo(0,1,"success"); ruleChainMetaData.addConnectionInfo(0, 1, "success");
ruleChainMetaData.addConnectionInfo(0,2,"fail"); ruleChainMetaData.addConnectionInfo(0, 2, "fail");
ruleChainMetaData.addConnectionInfo(1,2,"success"); ruleChainMetaData.addConnectionInfo(1, 2, "success");
ruleChainMetaData.addConnectionInfo(2,0,"success"); ruleChainMetaData.addConnectionInfo(2, 0, "success");
return ruleChainMetaData; return ruleChainMetaData;
} }
@ -582,16 +663,16 @@ public class RuleChainServiceTest extends AbstractServiceTest {
private RuleChain getRuleChain() { private RuleChain getRuleChain() {
String ruleChainStr = "{\n" + String ruleChainStr = "{\n" +
" \"name\": \"Root Rule Chain\",\n" + " \"name\": \"Root Rule Chain\",\n" +
" \"type\": \"CORE\",\n" + " \"type\": \"CORE\",\n" +
" \"firstRuleNodeId\": {\n" + " \"firstRuleNodeId\": {\n" +
" \"entityType\": \"RULE_NODE\",\n" + " \"entityType\": \"RULE_NODE\",\n" +
" \"id\": \"91ad0b00-e779-11ee-9cf0-15d8b6079fdb\"\n" + " \"id\": \"91ad0b00-e779-11ee-9cf0-15d8b6079fdb\"\n" +
" },\n" + " },\n" +
" \"debugMode\": false,\n" + " \"debugMode\": false,\n" +
" \"configuration\": null,\n" + " \"configuration\": null,\n" +
" \"additionalInfo\": null\n" + " \"additionalInfo\": null\n" +
"}"; "}";
return JacksonUtil.fromString(ruleChainStr, RuleChain.class); return JacksonUtil.fromString(ruleChainStr, RuleChain.class);
} }
} }