Search in sources :

Example 1 with RuleNodeUpdateResult

use of org.thingsboard.server.common.data.rule.RuleNodeUpdateResult in project thingsboard by thingsboard.

the class DefaultTbRuleChainService method updateRelatedRuleChains.

@Override
public List<RuleChain> updateRelatedRuleChains(TenantId tenantId, RuleChainId ruleChainId, RuleChainUpdateResult result) {
    Set<RuleChainId> ruleChainIds = new HashSet<>();
    log.debug("[{}][{}] Going to update links in related rule chains", tenantId, ruleChainId);
    if (result.getUpdatedRuleNodes() == null || result.getUpdatedRuleNodes().isEmpty()) {
        return Collections.emptyList();
    }
    Set<String> oldLabels = new HashSet<>();
    Set<String> newLabels = new HashSet<>();
    Set<String> confusedLabels = new HashSet<>();
    Map<String, String> updatedLabels = new HashMap<>();
    for (RuleNodeUpdateResult update : result.getUpdatedRuleNodes()) {
        var oldNode = update.getOldRuleNode();
        var newNode = update.getNewRuleNode();
        if (isOutputRuleNode(newNode)) {
            try {
                oldLabels.add(oldNode.getName());
                newLabels.add(newNode.getName());
                if (!oldNode.getName().equals(newNode.getName())) {
                    String oldLabel = oldNode.getName();
                    String newLabel = newNode.getName();
                    if (updatedLabels.containsKey(oldLabel) && !updatedLabels.get(oldLabel).equals(newLabel)) {
                        confusedLabels.add(oldLabel);
                        log.warn("[{}][{}] Can't automatically rename the label from [{}] to [{}] due to conflict [{}]", tenantId, ruleChainId, oldLabel, newLabel, updatedLabels.get(oldLabel));
                    } else {
                        updatedLabels.put(oldLabel, newLabel);
                    }
                }
            } catch (Exception e) {
                log.warn("[{}][{}][{}] Failed to decode rule node configuration", tenantId, ruleChainId, newNode.getId(), e);
            }
        }
    }
    // Remove all output labels that are renamed to two or more different labels, since we don't which new label to use;
    confusedLabels.forEach(updatedLabels::remove);
    // Remove all output labels that are renamed but still present in the rule chain;
    newLabels.forEach(updatedLabels::remove);
    if (!oldLabels.equals(newLabels)) {
        ruleChainIds.addAll(updateRelatedRuleChains(tenantId, ruleChainId, updatedLabels));
    }
    return ruleChainIds.stream().map(id -> ruleChainService.findRuleChainById(tenantId, id)).collect(Collectors.toList());
}
Also used : RequiredArgsConstructor(lombok.RequiredArgsConstructor) JacksonUtil(org.thingsboard.common.util.JacksonUtil) TbRuleChainInputNode(org.thingsboard.rule.engine.flow.TbRuleChainInputNode) RuleChainMetaData(org.thingsboard.server.common.data.rule.RuleChainMetaData) HashMap(java.util.HashMap) RuleNodeId(org.thingsboard.server.common.data.id.RuleNodeId) TenantId(org.thingsboard.server.common.data.id.TenantId) RuleChainUpdateResult(org.thingsboard.server.common.data.rule.RuleChainUpdateResult) RuleChainService(org.thingsboard.server.dao.rule.RuleChainService) TreeSet(java.util.TreeSet) EntityRelation(org.thingsboard.server.common.data.relation.EntityRelation) RelationService(org.thingsboard.server.dao.relation.RelationService) HashSet(java.util.HashSet) RuleNodeUpdateResult(org.thingsboard.server.common.data.rule.RuleNodeUpdateResult) TbCoreComponent(org.thingsboard.server.queue.util.TbCoreComponent) Service(org.springframework.stereotype.Service) Map(java.util.Map) TbRuleChainInputNodeConfiguration(org.thingsboard.rule.engine.flow.TbRuleChainInputNodeConfiguration) RuleNode(org.thingsboard.server.common.data.rule.RuleNode) Set(java.util.Set) Collectors(java.util.stream.Collectors) TbRuleChainOutputNode(org.thingsboard.rule.engine.flow.TbRuleChainOutputNode) RuleChainOutputLabelsUsage(org.thingsboard.server.common.data.rule.RuleChainOutputLabelsUsage) Slf4j(lombok.extern.slf4j.Slf4j) List(java.util.List) RuleChain(org.thingsboard.server.common.data.rule.RuleChain) RuleChainId(org.thingsboard.server.common.data.id.RuleChainId) Comparator(java.util.Comparator) Collections(java.util.Collections) RuleNodeUpdateResult(org.thingsboard.server.common.data.rule.RuleNodeUpdateResult) HashMap(java.util.HashMap) RuleChainId(org.thingsboard.server.common.data.id.RuleChainId) HashSet(java.util.HashSet)

Example 2 with RuleNodeUpdateResult

use of org.thingsboard.server.common.data.rule.RuleNodeUpdateResult in project thingsboard by thingsboard.

the class BaseRuleChainService method saveRuleChainMetaData.

@Override
@Transactional
public RuleChainUpdateResult saveRuleChainMetaData(TenantId tenantId, RuleChainMetaData ruleChainMetaData) {
    Validator.validateId(ruleChainMetaData.getRuleChainId(), "Incorrect rule chain id.");
    RuleChain ruleChain = findRuleChainById(tenantId, ruleChainMetaData.getRuleChainId());
    if (ruleChain == null) {
        return RuleChainUpdateResult.failed();
    }
    ConstraintValidator.validateFields(ruleChainMetaData);
    List<RuleNodeUpdateResult> updatedRuleNodes = new ArrayList<>();
    if (CollectionUtils.isNotEmpty(ruleChainMetaData.getConnections())) {
        validateCircles(ruleChainMetaData.getConnections());
    }
    List<RuleNode> nodes = ruleChainMetaData.getNodes();
    List<RuleNode> toAddOrUpdate = new ArrayList<>();
    List<RuleNode> toDelete = new ArrayList<>();
    Map<RuleNodeId, Integer> ruleNodeIndexMap = new HashMap<>();
    if (nodes != null) {
        for (RuleNode node : nodes) {
            if (node.getId() != null) {
                ruleNodeIndexMap.put(node.getId(), nodes.indexOf(node));
            } else {
                toAddOrUpdate.add(node);
            }
        }
    }
    List<RuleNode> existingRuleNodes = getRuleChainNodes(tenantId, ruleChainMetaData.getRuleChainId());
    for (RuleNode existingNode : existingRuleNodes) {
        deleteEntityRelations(tenantId, existingNode.getId());
        Integer index = ruleNodeIndexMap.get(existingNode.getId());
        RuleNode newRuleNode = null;
        if (index != null) {
            newRuleNode = ruleChainMetaData.getNodes().get(index);
            toAddOrUpdate.add(newRuleNode);
        } else {
            updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode, null));
            toDelete.add(existingNode);
        }
        updatedRuleNodes.add(new RuleNodeUpdateResult(existingNode, newRuleNode));
    }
    if (nodes != null) {
        for (RuleNode node : toAddOrUpdate) {
            node.setRuleChainId(ruleChain.getId());
            RuleNode savedNode = ruleNodeDao.save(tenantId, node);
            createRelation(tenantId, new EntityRelation(ruleChainMetaData.getRuleChainId(), savedNode.getId(), EntityRelation.CONTAINS_TYPE, RelationTypeGroup.RULE_CHAIN));
            int index = nodes.indexOf(node);
            nodes.set(index, savedNode);
            ruleNodeIndexMap.put(savedNode.getId(), index);
        }
    }
    for (RuleNode node : toDelete) {
        deleteRuleNode(tenantId, node.getId());
    }
    RuleNodeId firstRuleNodeId = null;
    if (nodes != null) {
        if (ruleChainMetaData.getFirstNodeIndex() != null) {
            firstRuleNodeId = nodes.get(ruleChainMetaData.getFirstNodeIndex()).getId();
        }
        if ((ruleChain.getFirstRuleNodeId() != null && !ruleChain.getFirstRuleNodeId().equals(firstRuleNodeId)) || (ruleChain.getFirstRuleNodeId() == null && firstRuleNodeId != null)) {
            ruleChain.setFirstRuleNodeId(firstRuleNodeId);
            ruleChainDao.save(tenantId, ruleChain);
        }
        if (ruleChainMetaData.getConnections() != null) {
            for (NodeConnectionInfo nodeConnection : ruleChainMetaData.getConnections()) {
                EntityId from = nodes.get(nodeConnection.getFromIndex()).getId();
                EntityId to = nodes.get(nodeConnection.getToIndex()).getId();
                String type = nodeConnection.getType();
                createRelation(tenantId, new EntityRelation(from, to, type, RelationTypeGroup.RULE_NODE));
            }
        }
        if (ruleChainMetaData.getRuleChainConnections() != null) {
            for (RuleChainConnectionInfo nodeToRuleChainConnection : ruleChainMetaData.getRuleChainConnections()) {
                RuleChainId targetRuleChainId = nodeToRuleChainConnection.getTargetRuleChainId();
                RuleChain targetRuleChain = findRuleChainById(TenantId.SYS_TENANT_ID, targetRuleChainId);
                RuleNode targetNode = new RuleNode();
                targetNode.setName(targetRuleChain != null ? targetRuleChain.getName() : "Rule Chain Input");
                targetNode.setRuleChainId(ruleChain.getId());
                targetNode.setType("org.thingsboard.rule.engine.flow.TbRuleChainInputNode");
                var configuration = JacksonUtil.newObjectNode();
                configuration.put("ruleChainId", targetRuleChainId.getId().toString());
                targetNode.setConfiguration(configuration);
                ObjectNode layout = (ObjectNode) nodeToRuleChainConnection.getAdditionalInfo();
                layout.remove("description");
                layout.remove("ruleChainNodeId");
                targetNode.setAdditionalInfo(layout);
                targetNode.setDebugMode(false);
                targetNode = ruleNodeDao.save(tenantId, targetNode);
                EntityRelation sourceRuleChainToRuleNode = new EntityRelation();
                sourceRuleChainToRuleNode.setFrom(ruleChain.getId());
                sourceRuleChainToRuleNode.setTo(targetNode.getId());
                sourceRuleChainToRuleNode.setType(EntityRelation.CONTAINS_TYPE);
                sourceRuleChainToRuleNode.setTypeGroup(RelationTypeGroup.RULE_CHAIN);
                relationService.saveRelation(tenantId, sourceRuleChainToRuleNode);
                EntityRelation sourceRuleNodeToTargetRuleNode = new EntityRelation();
                EntityId from = nodes.get(nodeToRuleChainConnection.getFromIndex()).getId();
                sourceRuleNodeToTargetRuleNode.setFrom(from);
                sourceRuleNodeToTargetRuleNode.setTo(targetNode.getId());
                sourceRuleNodeToTargetRuleNode.setType(nodeToRuleChainConnection.getType());
                sourceRuleNodeToTargetRuleNode.setTypeGroup(RelationTypeGroup.RULE_NODE);
                relationService.saveRelation(tenantId, sourceRuleNodeToTargetRuleNode);
            }
        }
    }
    return RuleChainUpdateResult.successful(updatedRuleNodes);
}
Also used : RuleNodeUpdateResult(org.thingsboard.server.common.data.rule.RuleNodeUpdateResult) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) HashMap(java.util.HashMap) RuleNode(org.thingsboard.server.common.data.rule.RuleNode) ArrayList(java.util.ArrayList) RuleChainId(org.thingsboard.server.common.data.id.RuleChainId) Validator.validateString(org.thingsboard.server.dao.service.Validator.validateString) EntityId(org.thingsboard.server.common.data.id.EntityId) EntityRelation(org.thingsboard.server.common.data.relation.EntityRelation) NodeConnectionInfo(org.thingsboard.server.common.data.rule.NodeConnectionInfo) RuleChain(org.thingsboard.server.common.data.rule.RuleChain) RuleNodeId(org.thingsboard.server.common.data.id.RuleNodeId) RuleChainConnectionInfo(org.thingsboard.server.common.data.rule.RuleChainConnectionInfo) Transactional(org.springframework.transaction.annotation.Transactional)

Aggregations

HashMap (java.util.HashMap)2 RuleChainId (org.thingsboard.server.common.data.id.RuleChainId)2 RuleNodeId (org.thingsboard.server.common.data.id.RuleNodeId)2 EntityRelation (org.thingsboard.server.common.data.relation.EntityRelation)2 RuleChain (org.thingsboard.server.common.data.rule.RuleChain)2 RuleNode (org.thingsboard.server.common.data.rule.RuleNode)2 RuleNodeUpdateResult (org.thingsboard.server.common.data.rule.RuleNodeUpdateResult)2 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)1 ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1 Comparator (java.util.Comparator)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1 Collectors (java.util.stream.Collectors)1 RequiredArgsConstructor (lombok.RequiredArgsConstructor)1 Slf4j (lombok.extern.slf4j.Slf4j)1 Service (org.springframework.stereotype.Service)1